给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
数组中的元素只能覆盖,不能删除
用双重for循环遍历,寻找到val时将后续元素向前移一位
设置两个指针,一个快指针和一个慢指针。
令慢指针在元素非val的时候向前移动,为val的时候停顿,并持续将快指针的指向的值赋予慢指针,覆盖val的值
最后慢指针的值就是数组的长度。
class Solution { public int removeElement(int[] nums, int val) { //单向双指针法 //一个指针指要删除的数,一个指下一个数 int slowIndex = 0; for (int fastIndex = 0; fastIndex < nums.length; fastIndex++) { //为val值时slowIndex停滞,下一次循环时快指针指向的内容替换慢指针指向的val if (val != nums[fastIndex]) { nums[slowIndex++] = nums[fastIndex]; } } return slowIndex; } }
设置左右两个指针:
在遍历时,右指针遇到的val值必然超出结果所得到的数组的界限,是要被抛弃的val,不需要进行覆盖操作。到两根指针相遇时,左指针指向数组的后一位,而右指针必然在左指针前一位(循环条件为left<=right),返回值为剩余数组的长度。
class Solution { public int removeElement(int[] nums, int val) { //双向双指针法 //一个指针指要删除的数,一个指不要删除的数 int n = nums.length; int leftIndex = 0, rightIndex = n - 1; while (leftIndex <= rightIndex) { //左指针从左开始找val while (leftIndex <= rightIndex && nums[leftIndex] != val) { ++leftIndex; } //右指针从右开始找非val while (leftIndex <= rightIndex && nums[rightIndex] == val) { --rightIndex; } //把右边的非val数替换到前面的val中,直接忽视末尾的val if (leftIndex < rightIndex) { //替换之后继续遍历 nums[leftIndex++] = nums[rightIndex--]; } } //leftIndex指向末尾的下一个元素,即数组长度;或rightIndex + 1(循环结束条件) return rightIndex + 1; } }