我几乎完成了这个问题的代码,我将在下面说明:
鉴于:
长度'n'(比如n = 10000)的数组,如下所示,
char **records = malloc(10000*sizeof(*records));
每个记录[i]都是一个字符指针,指向非空字符串。
records[i] = malloc(11);
字符串是固定长度的(10个字符+'\ 0')。
要求:
返回上面数组中最常出现的字符串。
但是现在,我感兴趣的是获得一个比我现在的原始算法稍微不那么残酷的算法,它是在两个for循环中筛选整个数组:(,将两个循环遇到的字符串临时存储类似大小的数组('n' - 如果所有都是唯一的字符串)用于与下一个字符串进行比较。内部循环从'外循环位置+ 1 '迭代到' n '。同时,我有一个大小相似的整数数组 - 'n',用于计算重复次数,每个i th 元素对应于i th 比较数组中的em>(唯一)字符串。然后找到最大的整数并在比较数组中使用其索引返回最常出现的字符串。
我希望我足够清楚。我自己对算法感到很惭愧,但必须这样做。我确信在C中有一个更聪明的方法。
周日愉快,
干杯!
答案 0 :(得分:3)
如果不擅长好的算法(谷歌,维基百科和Stackoverflow对我来说已经足够了),我脑子里的一个解决方案是对数组进行排序,然后使用单个循环来完成这些条目。只要当前字符串与前一个字符串相同,就增加该字符串的计数器。完成后,您将拥有一个字符串及其出现的“列表”,然后可以根据需要对其进行排序。
答案 1 :(得分:2)
在大多数语言中,通常的方法是构造一个哈希表,将字符串映射到计数。这具有O(N)复杂性。
例如,在Python中(尽管通常你会使用collections.Counter,甚至可以使用更专业的Python知识使这些代码更简洁,但我已经明确地将其用于演示)。
def most_common(strings):
counts = {}
for s in strings:
if s not in counts:
counts[s] = 0
counts[s] += 1
return max(counts, key=counts.get)
但是在C语言中,标准库中没有哈希表(尽管在C ++中你可以使用STL中的hash_map),因此可以进行排序和扫描。这是O(N.log(N))的复杂性,它比最优的更糟,但非常实用。
这是实现此目的的一些C(实际上是C99)代码。
int compare_strings(const void*s0, const void*s1) {
return strcmp((const char*)s0, (const char*)s1);
}
const char *most_common(const char **records, size_t n) {
qsort(records, n, sizeof(records[0]), compare_strings);
const char *best = 0; // The most common string found so far.
size_t max = 0; // The longest run found.
size_t run = 0; // The length of the current run.
for (size_t i = 0; i < n; i++) {
if (!compare_strings(records[i], records[i - run])) {
run += 1;
} else {
run = 1;
}
if (run > max) {
best = records[i];
max = run;
}
}
return best;
}