一.题目
二.知识点
数组,双指针
三.解法一
思考:
* 单指针:
*总体思想就是1个指针,指针i遍历(快指针),count做记录,它得从1开始,因为刚开始就是1个元素相同,当有相等的时候就是两个元素相同。
*当有元素和上一个相等的时候,count++,当count超过指定数,那么就执行左移操作(删除,但是通过元素左移一位代替),并将数组长度和i减去1,因为左移了,数组边小了。
*如果当前元素和上一个不相同,将count重置。
*每遍历完,i++
*最后返回的length就是删除后的元素长度。
代码:
class Solution {
//这个作用就是将所有的元素左移一位,这样相当于删除了
public void del(int[] nums,int index){
for(int i=index+1;i<nums.length;i++){
nums[i-1] = nums[i];
}
}
/*
*总体思想就是两个指针,一个指针i遍历(快指针),一个指针count做记录,它得从1开始,因为刚开始就是1个元素相同,当有相等的时候就是两个元素相同。
*当有元素和上一个相等的时候,count++,当count超过指定数,那么就执行左移操作(删除,但是通过元素左移一位代替),并将数组长度和i减去1,因为左移了,数组边小了。
*如果当前元素和上一个不相同,将count重置。
*每遍历完,i++
*最后返回的length就是删除后的元素长度。
**/
public int removeDuplicates(int[] nums) {
int max = 2;
int length = nums.length;
//这个就是记录有多少个相同元素,而最开始只有一个元素的时候,可以认为一个元素相同
int count = 1;
int i =1;
while(i<length){
//当前元素和上一个相同,那么count就加1,第一次相等的时候,说明两个元素相同
if(nums[i]==nums[i-1]){
count++;
//如果相同元素超过指定数目,那么就应该执行左移操作,并且数组整体减去1,i减去1,因为数组缩小了。
if(count>max){
del(nums,i);
length--;
i--;
}
}else{
count = 1;
}
i++;
}
return length;
}
}
四.解法二
思考:
双指针:就是找i遍历数组,j的话是慢指针,指向将来要被快指针覆盖的元素,count就是计数器。
什么思想呢,就是因为慢指针始终在前面,所以,它如果被覆盖了,对后面元素没有影响,继续遍历即可。
只要当前遍历的元素时候count不大于max,那么说明当前元素是合格的,而j就是指向合格元素,所以直接把j指向当前遍历的元素即可。反正j比较小,它被后面覆盖了,不会影响后面的值,这样的话,j就是数组长度。
代码
class Solution {
public int removeDuplicates(int[] nums) {
int max = 2;
//这个就是记录有多少个相同元素,而最开始只有一个元素的时候,可以认为一个元素相同
int count = 1;
int i =1;
int j = 1;//j一定得从1开始,因为下面的ifcount<=max做的操作,像除了第一位的元素以外,其他的后面元素,初始化的时候就做了一次覆盖操作(就是把后面的值给前面赋值)。
//而第一种元素初始化的时候没有做覆盖操作,为了防止这种情况,就从1开始,相当于0这个元素已经做了一次覆盖操作。
//假设输入是[1,1,1,2,2,2,2,3,3,3,3,3,3],如果从0开始的话,那么i=0,count=2,nums[0]=nums[1]=1;i=1,count=3;i=2,count=1;i=3,nums[1]=nums[3],这时候就1就少了一个1.
while(i<nums.length){
if(nums[i-1]==nums[i]){
count++;
}else{
count = 1;
}
if(count<=max){
//先做整个运算再加1
nums[j++] = nums[i];
}
i++;
}
//j是慢指针,虽然上面是从1开始的,实际上它是指向实际数组的最后一位,所以实际需要j+1,而上面while,if里面nums[j++]会++,所以质量就是最后的j加上1。
return j;
}
}