数组找重复函数疑问:某测试用例值来源不明
排序法查找数组重复元素的异常问题
我写了一段用排序法找数组重复元素的C语言函数,过了两个测试用例,但第二个测试用例里的取值逻辑我搞不懂。我知道能用XOR方法解决,但想弄明白这个测试用例里为什么会出现这种异常,以及它的取值逻辑是什么。
函数代码
int compare(const void * x1, const void * x2){ return ( *(int*)x1 - *(int*)x2 ); } int* findDuplicates(int* nums, int numsSize, int* returnSize) { int *p = (int*) malloc(numsSize * sizeof(int)); if(numsSize == 1){ *returnSize = 0; return p; } qsort(nums, numsSize, sizeof(int), compare); int k = 0; for(int i = 0; i < numsSize; i++){ if(i == numsSize - 1){ break; } if(nums[i] != nums[i + 1]){ continue; } p[k] = nums[i]; ++k; *returnSize +=1; } return p; }
异常原因分析
你的函数有两个核心问题,直接导致了测试用例中的异常:
returnSize未初始化:函数仅在numsSize==1时给*returnSize赋值0,其余场景下*returnSize会使用调用方传入的内存原始值(大概率是随机垃圾值),后续的*returnSize +=1会基于这个随机值累加,最终返回的结果长度完全错误。- 连续重复元素被多次记录:当数组中有连续多个相同元素时(比如
[2,2,2]),循环会在i=0时记录一次2,i=1时又因为nums[1] == nums[2]再记录一次2,导致结果数组中出现重复的重复元素,同时returnSize计数也会多算。
对应到你提到的第二个测试用例,异常的产生逻辑大致如下:
假设测试用例输入为[4,3,2,7,8,2,3,1],排序后变为[1,2,2,3,3,4,7,8]。你的循环会在i=1时记录2,i=2时因nums[2] != nums[3]跳过;i=3时记录3,i=4时跳过。但由于returnSize初始是随机值,最终返回的长度会是随机值+2,结果数组中前两个位置是正确的2和3,后面的位置则是malloc分配的未初始化垃圾值,看起来就像是“莫名获取到了数组里的某个值”。
修复后的代码
要解决这些问题,需要初始化returnSize,并在找到重复元素后跳过所有连续的相同元素:
int compare(const void * x1, const void * x2){ return ( *(int*)x1 - *(int*)x2 ); } int* findDuplicates(int* nums, int numsSize, int* returnSize) { int *p = (int*) malloc(numsSize * sizeof(int)); // 初始化返回长度为0 *returnSize = 0; if(numsSize <= 1){ return p; } qsort(nums, numsSize, sizeof(int), compare); int k = 0; for(int i = 0; i < numsSize; ){ if(i == numsSize - 1){ break; } if(nums[i] != nums[i + 1]){ i++; continue; } // 记录重复元素 p[k++] = nums[i]; (*returnSize)++; // 跳过所有连续相同元素,避免重复记录 while(i < numsSize - 1 && nums[i] == nums[i+1]){ i++; } i++; } // 重新分配内存,释放多余空间(可选,更规范) p = realloc(p, (*returnSize) * sizeof(int)); return p; }
内容的提问来源于stack exchange,提问作者Ruslan Pseush
相关产品推荐
相关产品推荐

