C++实现countDifferentNumbers统计数组不同值个数的问题排查
现有函数存在的问题
- 存在严重的数组越界风险:内层循环判断条件为
j < n,但循环体内访问的是v[j+1],当j执行到最大值n-1时,j+1的取值为n,已经超出数组合法的0~n-1下标范围,属于C++中明确的未定义行为,可能引发程序崩溃、内存数据错乱等问题。 - 核心计数逻辑完全偏离需求:当前代码的计数规则是“只要当前元素和后续位置的元素值相等,就给counter+1”,本质是统计所有重复值的匹配次数,而非统计不重复值的总数量。以题中给出的示例数组
{1,5,5,8,1,1}为例,现有代码运行后会得到4的错误结果,和正确返回值3存在明显偏差。 - 混入无关的打印逻辑:函数内部直接通过
cout打印匹配提示和元素值,作为承担纯计算职责的函数,这种写法会强行向输出流写入无关内容,破坏调用方的输出逻辑。 - 计数规则存在重复累加偏差:同一个元素如果和后续多个重复值匹配,会被多次累加计数,进一步放大最终结果和正确值的差距。
函数正确重设计方案
核心实现逻辑:遍历数组过程中,仅对“之前未在数组中出现过”的元素累加计数,重复出现的元素不再计入统计,最终得到的累加值就是数组中不同值的总数量。结合C++的标准库能力,可根据实际数组长度选择对应的实现方案:
低依赖朴素实现
这种实现不需要引入额外的标准库容器,代码逻辑直白,适合短数组场景,时间复杂度为O(n²),无外部依赖:
int countDifferentNumbers(int v[], int n) { // 边界场景处理:空数组直接返回0 if (n <= 0) return 0; int counter = 0; for (int i = 0; i < n; ++i) { bool isDuplicated = false; // 遍历当前元素之前的所有位置,判断相同值是否已经出现过 for (int j = 0; j < i; ++j) { if (v[j] == v[i]) { isDuplicated = true; break; } } // 未出现过相同值则计数+1 if (!isDuplicated) { counter++; } } return counter; }
基于标准库的高效实现
利用C++标准库自带的去重容器实现,代码精简运行效率高,适合长数组场景:
- 基于
std::set的实现:容器会自动对插入的元素去重,时间复杂度为O(nlogn)
// 需预先引入<set>头文件 #include <set> int countDifferentNumbers(int v[], int n) { if (n <= 0) return 0; // 通过数组的首尾地址直接构造set,自动完成全量去重 std::set<int> numSet(v, v + n); return static_cast<int>(numSet.size()); }
- 若追求更高的平均运行效率,可将上述代码中的
std::set替换为std::unordered_set,平均时间复杂度可优化至O(n),仅需引入<unordered_set>头文件即可使用。
内容的提问来源于stack exchange,提问作者41 72 6c
相关产品推荐
相关产品推荐

