这道题开始没思路,但是后来用双指针的分区域法一思考,基本很快就搞出来了。不过一是有个细节搞错了,二是还有很多地方可以优化。
class Solution { public int removeDuplicates(int[] nums) { //空数组特判 if(nums.length==0) {return 0;} int p1=-1,p2=0;//p1指向重复区开头,p2用于遍历 int lastNum=0; while(p2<nums.length) { if(p2==0) { lastNum=nums[0]; p2++; } else { if(nums[p2]==lastNum) { //重复了 if(p1==-1) { //开辟重复区 p1=p2; p2++; } else { p2++; } } else if(nums[p2]!=lastNum) { //没有重复,变换,修改lastnum lastNum=nums[p2]; if(p1==-1)// { p2++; } else { int num=nums[p1]; nums[p1]=nums[p2]; nums[p2]=num; p1++; p2++; } } } } //应该特判假如p1为-1时 if(p1==-1) {return nums.length;} else {return p1;} } }
代码开始写成这样,第一次错误是一直没有重复项时p1为初值-1。当然有几个p2++可以提出来。
public int removeDuplicates(int[] nums) { if(nums == null || nums.length == 0) return 0; int p = 0; int q = 1; while(q < nums.length){ if(nums[p] != nums[q]){ nums[p + 1] = nums[q]; p++; } q++; } return p + 1; }
官方的这种解法当然简洁很多,但感觉没有之前那种套路百试不爽。
本人代码简化后:
class Solution { public int removeDuplicates(int[] nums) { //空数组特判 if(nums.length==0) {return 0;} int p1=nums.length,p2=1;//p1指向重复区开头,p2用于遍历。这里p1初始值设成这个,就不用特判了
int lastNum=nums[0]; while(p2<nums.length) { if(nums[p2]==lastNum) { //重复了 if(p1==nums.length) { //开辟重复区 p1=p2; } } else if(nums[p2]!=lastNum) { //没有重复,变换,修改lastnum lastNum=nums[p2]; if(p1!=nums.length)// { int num=nums[p1]; nums[p1]=nums[p2]; nums[p2]=num; p1++; } } p2++; } //应该特判假如p1为-1时,这里第一次搞错了 return p1; } }