sl1673495 / leetcode-javascript

:beers: 喝杯小酒,一起做题。前端攻城狮从零入门算法的宝藏题库,根据知名算法老师的经验总结了 100+ 道 LeetCode 力扣的经典题型 JavaScript 题解和思路。已按题目类型分 label,一起加油。
2.08k stars 344 forks source link

移动零-283 #26

Open sl1673495 opened 4 years ago

sl1673495 commented 4 years ago
  1. 移动零

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

示例:

输入: [0,1,0,3,12]
输出: [1,3,12,0,0]

说明:

必须在原数组上操作,不能拷贝额外的数组。尽量减少操作次数。 https://leetcode-cn.com/problems/move-zeroes

思路

暴力法

先遍历一次,找出所有 0 的下标,然后删除掉所有 0 元素,再 push 相应的 0 的个数到 末尾。

var moveZeroes = function (nums) {
  let zeros = []
  for (let i = 0; i < nums.length; i++) {
    if (nums[i] === 0) {
      zeros.push(i)
    }
  }
  for (let j = zeros.length - 1; j >= 0; j--) {
    nums.splice(zeros[j], 1)
  }
  for (let j = 0; j < zeros.length; j++) {
    nums.push(0)
  }
  return nums
}

双指针

慢指针 j 从 0 开始,当快指针 i 遍历到非 0 元素的时候,i 和 j 位置的元素交换,然 后把 j + 1。

也就是说,快指针 i 遍历完毕后, [0, j) 区间就存放着所有非 0 元素,而剩余的[j, n]区间再遍历一次,用 0 填充满即可。

gif

var moveZeroes = function (nums) {
  let j = 0

  for (let i = 0; i < nums.length; i++) {
    if (nums[i] !== 0) {
      nums[j] = nums[i]
      j++
    }
  }

  while (j < nums.length) {
    nums[j] = 0
    j++
  }
}

双指针(交换位置)

在上面的算法里,快指针遍历完成后,还要遍历慢指针到末尾来填充 0。实际上这题只要遇 到非 0 元素,就把当前位置的值和慢指针位置 j 的值交换,然后只有此时 j 才 + 1,即 可完成。

gif

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
}