C语言中数组排除唯一值时如何保留重复元素的原始顺序
解决思路与修改后的代码
你的问题核心是需要保留原数组中所有出现过至少两次的元素,并且严格维持它们在原列表中的出现顺序。原代码的问题在于没有先统计元素的出现频率,直接筛选的话要么会打乱顺序,要么会漏掉重复出现的实例。
这里提供两种可行的修改方案,从高效到灵活覆盖不同场景:
方案一:基于数组统计频率(适合元素范围可控的场景)
这种方法先遍历一次数组统计每个数字的出现次数,再重新遍历原数组,只保留那些出现次数≥2的元素,完美维持原顺序:
#include <stdio.h> #include <stdlib.h> // 假设元素范围在 -1000 到 1000 之间,可根据实际需求调整边界 #define MIN_VAL -1000 #define MAX_VAL 1000 int main() { int i, x, array[1000], result[1000]; int count[MAX_VAL - MIN_VAL + 1] = {0}; // 初始化计数数组全为0 int result_len = 0; printf("Please enter the number of integers in your list:\n"); scanf("%d", &x); printf("Please enter the list of numbers:\n"); for (i = 0; i < x; i++) { scanf("%d", &array[i]); // 处理负数的索引偏移,确保所有元素都能对应到计数数组的合法位置 count[array[i] - MIN_VAL]++; } // 再次遍历原数组,筛选出重复出现的元素 for (i = 0; i < x; i++) { if (count[array[i] - MIN_VAL] >= 2) { result[result_len++] = array[i]; } } // 输出最终结果 printf("\nThe corrected list (keeping duplicates in original order):\n"); for (i = 0; i < result_len; i++) { printf("%d ", result[i]); } printf("\n"); return 0; }
代码说明:
- 先通过计数数组统计每个元素的出现频率,负数元素通过偏移量转换为合法的数组索引。
- 第二次遍历原数组时,只保留那些出现过至少两次的元素,这样完全遵循了原数组的顺序,不会打乱任何重复元素的出现位置。
方案二:基于双重循环(适合任意元素范围,无需预设边界)
如果不确定输入元素的范围,不想用固定大小的计数数组,可以用双重循环标记重复元素,同时避免重复判断:
#include <stdio.h> #include <stdlib.h> int main() { int i, j, x, array[1000], result[1000]; int is_duplicate[1000] = {0}; // 标记对应位置的元素是否为重复项 int result_len = 0; printf("Please enter the number of integers in your list:\n"); scanf("%d", &x); printf("Please enter the list of numbers:\n"); for (i = 0; i < x; i++) { scanf("%d", &array[i]); } // 先标记所有重复出现的元素位置 for (i = 0; i < x; i++) { if (is_duplicate[i]) continue; // 已经标记过的元素直接跳过 int has_duplicate = 0; for (j = i + 1; j < x; j++) { if (array[i] == array[j]) { has_duplicate = 1; is_duplicate[j] = 1; // 标记后续的重复元素位置 } } if (has_duplicate) { is_duplicate[i] = 1; // 标记当前元素为重复项 } } // 按原顺序收集所有重复元素 for (i = 0; i < x; i++) { if (is_duplicate[i]) { result[result_len++] = array[i]; } } // 输出最终结果 printf("\nThe corrected list (keeping duplicates in original order):\n"); for (i = 0; i < result_len; i++) { printf("%d ", result[i]); } printf("\n"); return 0; }
代码说明:
- 用
is_duplicate数组标记每个位置的元素是否属于重复项:外层循环遍历每个元素,内层循环检查后续是否有相同元素,若有则标记当前元素和所有后续重复元素。 - 最后遍历原数组,把所有标记为重复的元素按顺序加入结果数组,确保所有重复实例都被保留且顺序不变。
两种方案都能解决你的问题,第一种时间复杂度为O(n)效率更高,第二种无需预设元素范围,适配性更强。
内容的提问来源于stack exchange,提问作者DZtron
相关产品推荐
相关产品推荐

