要努力考上研啦,每晚都刷算法了,从开始做leet开始,做了几天,后来好久都没有动它,现在不动不行了。
这次做的leetcode中文网,省去翻译的时间,相对节约一些时间,因为白天复习,晚上只能抽很少时间来做题。
这些题是按照中文网探索页面从简单到难一道一道的做的。
一.题目
给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
示例 1:
给定数组 nums = [1,1,2],
函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1
, 2
。
你不需要考虑数组中超出新长度后面的元素。
示例 2:
给定 nums = [0,0,1,1,1,2,2,3,3,4],
函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0
, 1
, 2
, 3
, 4
。
你不需要考虑数组中超出新长度后面的元素。
说明:
为什么返回数值是整数,但输出的答案是数组呢?
请注意,输入数组是以“引用”方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。
你可以想象内部操作如下:
// **nums** 是以“引用”方式传递的。也就是说,不对实参做任何拷贝
int len = removeDuplicates(nums);
// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中**该长度范围内**的所有元素。
for (int i = 0; i < len; i++) {
print(nums[i]);
}
2.我的想法
双指针法
int removeDuplicates(int* nums, int numsSize) {
int temp = 0; //模拟标志位指针
int i;//模拟工作指针
//判空
if(numsSize == 0){
return 0;
}
for(i = 0;i < numsSize;i++){
//工作指针开始遍历,当发现不等于初始位的值的时候
if(nums[i] > nums[temp]){
nums[++temp] = nums[i];
}
}
return temp + 1;
}
下面说说为什么这么想?
首先关注题目找到要点,两点:
数组有序
处理完的数字只在意前几位,不需要考虑数组中超出新长度后面的元素既然有序,而且最后处理完前几位是有序不重复的,那么前面的数字多余的直接覆盖掉就可以了。
举个栗子:
[1,1,3,5,7,7,8]
最后处理完是这个样子的
[1,3,5,7,8,X,X]后面多余的不用管。那么这样就简单了,我们用双指针,两个指针执行不同的功能,一个用于读新数字,另一个用于指向目标位置。
int temp = 0; //模拟标志位指针
int i;//模拟工作指针
for(i = 0;i < numsSize;i++){
//工作指针开始遍历,当发现不等于初始位的值的时候
if(nums[i] > nums[temp]){
nums[++temp] = nums[i];
}
}
下面通过栗子来模拟一下这个过程
原始:[1,1,3,5,7,7,8]
n开始后移,第一次,两个1相等,不进条件语句,继续后移。
发现数字比1大的了,然后移动temp指针到下一位,将刚n读到的数字填进去。(这里就可以大胆的覆盖了,不必担心会不会影响其他数据)
同理接下来的过程
可以看到前几位已经被我们处理好了,最后两位也不用再管了,这个算法复杂度是O(n),只有一轮循环。
3.其他方法
太简单以至于没找到别的方法……