目录
删除元素专题
1.原地移除所有数值等于val的元素
1)快慢双指针
public static int removeElement(int[] nums, int val) {
int slow = 0;
//fast充当了快指针的角色
for (int fast = 0; fast < nums.length; fast++) {
if (nums[fast] != val) {
nums[slow] = nums[fast];
slow++;
}
}
//最后剩余元素的数量
return slow;
}
快慢指针相当于定义了两个变量,fast走得快,遍历数组nums,找到nums中等于val的元素拷贝到slow走过的轨迹中。
2)对撞双指针
public int removeElement(int[] nums, int val) {
int left=0;
int right=nums.length-1;
for(left=0;left<=right; ){
if(nums[left]==val&&nums[right]!=val){
int temp=nums[left];
nums[left]=nums[right];
nums[right]=temp;
}
if(nums[left]!=val) left++;
if(nums[right]==val) right--;
}
return left;
}
left,right两个从数组头和尾分别开始走,当nums[left]等于val并且nums[right]不等于right的时候交换数组中两个位置的元素,否则都相向遍历,直到left==right,遍历完成,最后返回的left就是删除val元素后nums数组剩余元素的个数。
3)拓展:"对撞双指针+覆盖"法
public int removeElement(int[] nums, int val) {
int right=nums.length-1;
for(int left=0;left<=right; ){
if(nums[left]==val){
nums[left]=nums[right];
right--;
}else{
left++;
}
}
return right+1;
}
对方法2的拓展,把交换改为覆盖,我们的目的是删除val元素,所以并不关心val元素到哪里,因此覆盖一定程度上可以减少代码量,最后返回right+1。
为什么right要加一? 当nums[left]==val时,我们用nums[right]覆盖nums[left],并使right往前移一位, 因为开始right是作为索引存在,最后要返回的是剩余元素的个数。
补充一下:方法二中为什么返回left,开始时设置left=0,而后只要nums[left]!=val就使left++,交换后还会判断一下使left++,自然返回的就是删除val元素后nums数组剩余元素的个数了。
2.删除有序数组的重复项
public int removeDuplicates(int[] nums) {
int slow=1;
for(int fast=0;fast<nums.length;fast++){
if(nums[fast]!=nums[slow-1]){
nums[slow]=nums[fast];
slow++;
}
}
return slow;
}
先使slow=1,第一个元素算一个,进入for循环fast遍历数组,遇到新元素添加到slow走过的轨迹,slow++,最后返回slow,数组剩余元素的个数。
文章介绍了在数组中删除特定值和去除有序数组重复项的三种指针技巧,包括原地移除、快慢双指针和对撞双指针的扩展版本。
1399

被折叠的 条评论
为什么被折叠?



