如何避免统计数组元素频率时重复计算已统计的元素?
解决数组元素重复统计的问题
你的核心问题是重复元素触发了多次全数组统计,导致同一个元素的计数被反复累加。比如输入里的元素1出现两次,原代码会对它执行两次全数组遍历,每次都给status[0]加2,最终得到4,而非正确的2。
最简解决方案:单次遍历直接统计
完全不用复杂逻辑,直接一次遍历数组,每个元素对应status的位置加1即可,时间复杂度从O(n²)降到O(n),代码更简洁:
// 先把status数组初始化为0 memset(status, 0, sizeof(status)); for (int x = 0; x < n; x++) { int bird = all[x]; status[bird - 1]++; // 遇到元素就直接给对应索引计数+1 }
为什么这个方法有效:
因为输入元素的范围是1-5,刚好对应status数组的5个索引(bird-1会把1转为0,5转为4)。遍历过程中每个元素只会被处理一次,自然不会出现重复统计的问题。用你的示例输入1 1 2 2 3测试:
- 遍历到第一个1,
status[0]变为1 - 遍历到第二个1,
status[0]变为2 - 遍历到第一个2,
status[1]变为1 - 遍历到第二个2,
status[1]变为2 - 遍历到3,
status[2]变为1
最终得到2 2 1 0 0,完全符合期望输出。
保留原双重循环逻辑的改进(不推荐)
如果一定要保留原有的双重循环思路,可以在遍历每个元素前,先检查它是否已经被统计过,若已统计则跳过:
memset(status, 0, sizeof(status)); for (int x = 0; x < n; x++) { int bird = all[x]; // 检查当前元素在之前的位置是否已经出现过 bool has_counted = false; for (int k = 0; k < x; k++) { if (all[k] == bird) { has_counted = true; break; } } if (has_counted) continue; // 跳过已统计的元素 // 正常统计当前元素的出现次数 for (int y = 0; y < n; y++) { if (all[x] == all[y]) { status[bird - 1]++; } } }
不过这种方法仍然是O(n²)的时间复杂度,不如单次遍历高效,只适合必须保留原逻辑的场景。
内容的提问来源于stack exchange,提问作者NORAGAMI
相关产品推荐
相关产品推荐

