算法--数组--移除元素

68 阅读2分钟

算法--数组--移除元素

力扣题目链接

给你一个数组 nums  和一个值 val,你需要 原地 移除所有数值等于  val  的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。

示例  2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。 你不需要考虑数组中超出新长度后面的元素。

1 解答

先写再看噢~

解答

这个讲得很详细👉代码随想录

1.1 思路

  1. 遍历数组,找到 =val 的值,和!=val的换位置,一步一步移到后边
  2. 找到一个 =val 的,和后边一个比较,后边一个 !=val ,换位置(但如果是 [1,2,3]->[2,3,1] 换位置的次数就多了
  3. 改进,从后往前比,找到一个=val的,和最后的比,不一样和倒数第二比
  4. 返回新长度:交换的数量好得出。然后,找 !=val的数量,即第一层循环 nums[i] !== val 的个数,以及 nums[i] === val 下交换了的个数
// 不使用js的数组实例方法,仅用最基础的语法,便于转换到其他语言

/**
 * @param {number[]} nums
 * @param {number} val
 * @return {number}
 */
var removeElement = function (nums, val) {
  let count = 0;

  for (let i = 0; i < nums.length; i++) {
    if (nums[i] === val) {
      for (let j = nums.length - 1; j > i; j--) {
        if (nums[j] !== val) {
          let mid = nums[i];
          nums[i] = nums[j];
          nums[j] = mid;
          count++; // 交换次数
          break;
        }
      }
    } else {
      count++;
    }
  }

  return count;
};
  • 时间复杂度:O(n^2)
  • 空间复杂度:O(1)

两次循环 时间复杂度 n^2 了

1.2 改进--双指针法

因为不用管后面的值,所以不是非要交换,覆盖也行,所以可以找到 !=val 的值,依次放在前面

双指针法(快慢指针法): 通过一个快指针和慢指针在一个 for 循环下完成两个 for 循环的工作。

定义快慢指针

  • 快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
  • 慢指针:指向更新 新数组下标的位置

删除过程如下:

27.移除元素-双指针法

双指针法(快慢指针法)在数组和链表的操作中是非常常见的,很多考察数组、链表、字符串等操作的面试题,都使用双指针法。

var removeElement1 = (nums, val) => {
  let count = 0; // 慢指针
  for (let i = 0; i < nums.length; i++) {
    // 快指针
    if (nums[i] != val) {
      nums[count] = nums[i];
      count++;
    }
  }

  return count;
};

const nums = [3, 2, 1, 4];
const val = 2;
removeElement1(nums, val);