27.移除数组
题目
不用辅助数组,原地移除(删除)数组nums
中的等于val
的元素,被移出的部分不用管
三种方法
(重点)快慢双指针:把一个数组当两个用(顺序不变)
- 快指针:遍历旧数组,找要装进新数组的元素
- 慢指针:新数组下标
/**
* @param {number[]} nums
* @param {number} val
* @return {number}
*/
var removeElement = function(nums, val) { //快(老)慢(新)双指针
let slow = 0 //慢指针相当于新的数组下标
for (let fast = 0; fast < nums.length; fast++) { //快指针遍历旧数组
if (nums[fast] !== val) { //不是要移除元素时加入新数组
nums[slow++] = nums[fast]
}
}
return slow //返回数组个数
};
前后双指针:把不要的数移到最后(顺序变)
-
- 前指针:从前面开始找找不要的数
- 后指针:从后面找要的数,交换
/**
* @param {number[]} nums
* @param {number} val
* @return {number}
*/
var removeElement = function(nums, val) { //前(找要删)后(找不删)双指针
let l = 0,r = nums.length - 1; //区间为左闭右闭[]
while(l <= r){ //继续循环,进行下一次查找的条件
// 下面加 l <= r 是为了防止找的时候 指针穿过
while(l <= r && nums[l] !== val) l++; //找左边=val要删的值
while(l <= r && nums[r] === val) r--; //找右边!=val不删的值
// 一定要l < r时才覆盖,最后一次退出循环时,l > r不能交换
if(l < r) nums[l++] = nums[r--];//用不删的值覆盖要删的
//保持指针指向下一个要判断的值
}
return l; //l找被移除的,最后正好是指向第一个不满足的,也就是size大小
};
最后代码还是很简洁滴~
let l = 0, r = nums.length - 1
while (l <= r) {
while (l <= r && nums[l] !== val) l++
while (l <= r && nums[r] === val) r--
if(l < r) nums[l++] = nums[r--]
}
return l
注意暴力解法的代码细节(顺序不变)
i
先找到要删的数- 把后面的都往前移一位
- 注意:因为
i
后所有数都前移了一位,i
也得往前移一个,才能下一次for
循环i++
后指向下一个要判断的值(不然直接++会跳过刚移到i
位置上的数) - 在移动的过程中数组长度变化,循环条件应该为变化的
size
/**
* @param {number[]} nums
* @param {number} val
* @return {number}
*/
var removeElement = function(nums, val) { //暴力
let size = nums.length //nums.length为数组实际大小不会改变,size等会要返回的删除之后的大小
for (let i = 0; i < size; i++) {
if (nums[i] === val) { //找到要删除的值
for (let j = i + 1; j < size; j++) {
nums[j-1] = nums[j]
}
size--; //数组大小减一
i--; //i后面的值都向前移动了一位,如果i不前移,接下来执行i++会跳过一个数没判断,所以一定要i--
}
}
return size
};