【LeetCode】 移除元素&移动零 - 双指针 - 快慢指针 - 对撞指针

455 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

今天再来一个简单题,刷爆他~

27. 移除元素【简单】

leetcode-cn.com/problems/re…

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

【解法】快慢指针

删除有序数组中的重复项的思路一样,快指针i用来遍历一遍nums,慢指针j用来维持数组【不包含val元素】

  • 【注意】这题判断语句内部的执行顺序与26题不一样,先进行赋值再自增
  • 【注意】由于后自增,所以最后返回值已不需要手动+1
/**
 * @param {number[]} nums
 * @param {number} val
 * @return {number}
 */
var removeElement = function(nums, val) {
    let j = 0;
    for(let i = 0; i< nums.length; i++){
        if(nums[i] !== val){
            nums[j] = nums[i];
            j++;
        }
    }
    return j;
};

在这里插入图片描述

【解法二】对撞指针

由于题目对元素顺序没有要求,所以可以在碰到需要舍弃的元素(等于val的元素)时,用最后的元素替代即可

定义左右两个对撞指针

var removeElement = function(nums, val) {
  let left = 0;
  let right = nums.length - 1;
  while (left <= right) {
    if (nums[left] === val) {
      nums[left] = nums[right];
      right--;
    } else {
      left++;
    }
  }
  return left;
};

在这里插入图片描述

283. 移动零【简单】

leetcode-cn.com/problems/mo…

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

【解法一】快慢指针 + 两次遍历

快指针i遍历数组 慢指针j维持非零条件【只有元素不为0,j才右移,这样保证了数组的长度就是所有非0元的个数】

这个和第27题相似

/**
 * @param {number[]} nums
 * @return {void} Do not return anything, modify nums in-place instead.
 */
var moveZeroes = function(nums) {
    let j = 0;
    for(let i = 0; i < nums.length; i++){
        if(nums[i] !== 0){
        	// 将不为0的元素都保存下来
            nums[j] = nums[i];
            j++;
        }
    }
    // 剩下的位置置0
    for(;j<nums.length;j++){
        nums[j] = 0
    }
};

【解法二】快慢指针 + 一次遍历 + 交换元素

/**
 * @param {number[]} nums
 * @return {void} Do not return anything, modify nums in-place instead.
 */
var moveZeroes = function(nums) {
    let j = 0;
    for(let i = 0; i < nums.length; i++){
        if(nums[i] !== 0){
            swap(nums, i, j);
            j++;
        }
    }
};

function swap(nums, i, j){
    let temp = nums[i];
    nums[i] = nums[j];
    nums[j] = temp;
}