Problem Description
- 在一个递增有序的数组中,有数值相同的元素存在,程序的功能是去掉数值相同的元素,使数组中不再有重复的元素。
- 例如:(7,10,10,21,30,42,42,42,51)将变成(7,10,21,30,42,51)。
- 主函数main中,首先输入有序数组的元素数目及各元素的值,然后将数组及元素数目传入函数fun中,函数fun完成删除重复元素的操作。
- 要求:尽量优化算法的时间复杂度与空间复杂度。
解题思路
- 用int类型数组nums保存有序元素。
- 用变量j表示去重后数组的指针,初值为0,变量i表示遍历数组nums的指针,初值为1。
- 通过对比i和j指向的数组元素,若相同,则指针i后移,若不同,则指针j后移,并将i位置的元素赋值给j位置。
- 遍历完整个nums数组,去重完成,j的值为后移次数,即不同元素对比次数,去重数组的元素数目为j + 1。
- 时间复杂度为O(n),n为数组元素数目;空间复杂度为O(1)。
经验总结
- 一开始使用的是count数组记录元素是否出现,若输入的元素过大,则空间复杂度随之上涨。
- 用双指针的思想,空间复杂度始终为O(1)。
代码实现(C)
#include <stdio.h>
#define MaxSize 1000
void fun(int nums[], int *n) {
if (*n <= 1) return;
int j = 0;
for (int i = 1; i < *n; ++i) {
if (nums[j] != nums[i]) {
j++;
nums[j] = nums[i];
}
}
*n = j + 1;
}
int main() {
int nums[MaxSize], n;
while (~scanf("%d", &n)) {
for (int i = 0; i < n; ++i)
scanf("%d", &nums[i]);
fun(nums, &n);
for (int i = 0; i < n; ++i)
printf("%d ", nums[i]);
}
return 0;
}