题目:给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
示例一:
给定数组 nums = [1,1,2],
函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 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]);
}
标准参考一:
class Solution {
public int removeDuplicates(int[] nums) {
if(nums == null || nums.length == 0) return 0;
int count = 1;
for(int i=1;i<nums.length;i++){
if(nums[i-1] != nums[i]){
nums[count++] = nums[i];
}
}
return count;
}
}
标准参考二:
class Solution {
public int removeDuplicates(int[] nums) {
int index=0;
for(int i =1 ; i < nums.length ; i++){
if ( nums[i] != nums[index]){
index ++;
nums[index] = nums[i];
}
}
return ++index;
}
}
小白答案:
public int removeDuplicates(int[] nums) {
if(nums.length==0)return 0;
int j=1;
for(int i=0;i<nums.length;i++) {
j=i+1;
if(j>=nums.length)break;
int temp=j;
while(nums[i]==nums[j]) {
j++;
if(j>=nums.length)return i+1;
}
for(int m=temp;m<j;m++) {
nums[m]=nums[j];
}
for(int k=j;k<nums.length;k++) {
if(j>=nums.length-1)break;
nums[k]=nums[j++];
}
}
return nums.length;
}
小白是一个大学三年级的学生,因为平时在学校做开发相对较多,也没有专门的去深究过算法,抱着想要学好的心态开始了自己的算法之路,如果在自己的文章中有不当之处,或者有能给予小白指导,欢迎留言。
下面就讲一下自己对整个题目的理解及解题思路,并红着脸大致的讲解下好算法的妙处。
这是一道初级算法题。根据该题目的说明,就是去掉数组中重复的元素,并且不借助其他容器,实现“原地“”删除。刚拿到这道题目的时候原地爆炸,心里面在想:我这歌Set集合,貌似我只要把数组中的元素添加进去,他就会自动去重。当正准备写的时候,看了一下返回值,我的天,返回的是int类型,也就是说返回的是长度,传进来的nums[]数组我对他没有任何改动通过set集合去重,有什么用呢??所以马上有回过头看了两边题目,仔细的分析了下,我通过for循环,从第一个数组元素a[i]开始和后面的元素比较,如果相同,就该元素接着和后面的元素比较,这时里面就嵌套了个while循环,知道比较到不同值的元素a[j],此时我从a[i]到a[j]的所有元素全部更新为a[j],此处全部更新为的是防止出现1,2,1,2..这样的情况,由此就能将所有不同的元素全部赋值到数组的前端,并返回相应的长度。
相对参考一和参考二的答案,自己一下子就懵了。不是说看不懂,是因为发现自己在还没有发现说明中的元素规律就开始写了,比较的时候应该是a[i],a[i-1],同时i往增大的方向上去就可以了,没有必要说我的左边一端固定死了,通过右端的下标左右移动,这个是最重要的一点。其次就是发现了个大问题,就是自己在写for循环的时候喜欢写成:
for(int i=0;i<nums.length;i++){
if(a[i]==a[i++]){
....
}
}
而参考中的写法是:
for(int i=1;i<nums.length;i++){
if(a[i-1]==a[i]){
....
}
}
显然,参考的写法能够避免大量的数组越界判断,是一个小技巧。