目录

LC 1089. 复写零 (opens new window) (opens new window)

简单

# 问题描述

给你一个长度固定的整数数组 arr,请你将该数组中出现的每个零都复写一遍,并将其余的元素向右平移。

注意:请不要在超过该数组长度的位置写入元素。

要求:请对输入的数组 就地 进行上述修改,不要从函数返回任何东西。

示例 1:

输入:[1,0,2,3,0,4,5,0]
输出:null
解释:调用函数后,输入的数组将被修改为:[1,0,0,2,3,0,0,4]

示例 2:

输入:[1,2,3]
输出:null
解释:调用函数后,输入的数组将被修改为:[1,2,3]

提示:

  • 1 <= arr.length <= 10000
  • 0 <= arr[i] <= 9

# 队列

创建一个队列,队列里面存放的是遇到 00 之后接下来需要输出的数字,当遇到第一个 00 时,入队一个 00(意思是当前 00 的下一个数字是 00),然后继续遍历,当队列不为空时,将当前数字入队,如果当前数字是 00,则入队两次,然后队首元素出队,占领当前位置。

/**
 * @param {number[]} arr
 * @return {void} Do not return anything, modify arr in-place instead.
 */
var duplicateZeros = function (arr) {
  const queue = []
  for (let i = 0; i < arr.length; i++) {
    const num = arr[i]
    if (queue.length) {
      if (num === 0) {
        queue.push(0)
      }
      queue.push(num)
      arr[i] = queue.shift()
    } else if (num === 0) {
      queue.push(0)
    }
  }
}
  • 时间复杂度:O(n)O(n),需要遍历数组一次。
  • 空间复杂度:O(n)O(n),需要一个队列来存放后续的数。

# 栈

创建一个栈,遍历数组,当遇到 00 时,将 00 入栈两次,非 00 时,则入栈一次,当栈的长度跟原来数组长度一致时,停止遍历,这样就获得了一个复写 00 后效果的栈,然后倒序遍历数组,将栈内容改写到数组中。

/**
 * @param {number[]} arr
 * @return {void} Do not return anything, modify arr in-place instead.
 */
var duplicateZeros = function (arr) {
  const n = arr.length
  const stack = []
  for (let i = 0; i < n; i++) {
    if (arr[i] === 0) {
      stack.push(arr[i])
      if (stack.length === n) break
    }
    stack.push(arr[i])
    if (stack.length === n) break
  }
  for (let i = n - 1; i > -1; i--) {
    arr[i] = stack.pop()
  }
}
  • 时间复杂度:O(n)O(n),需要遍历数组两次。
  • 空间复杂度:O(n)O(n),需要开辟一个跟原数组相同大小的栈空间。

# 双指针

使用 ii 和 jj 两个指针,可以想像 ii 是指向原数组的头部位置,jj 指向目标数组的头部位置。然后开始遍历数组遇到过非 00 的数时,ii 和 jj 同时向后移动一个位置,如果遇到 00,则 ii 移动一个位置,jj 是指向目标数组,需要复写零,所以移动两个位置。当 jj 大于等于数组长度 nn 时停止遍历。

当 jj 走到的位置已超出数组长度时,ii 停在了需要被截断的位置的下一位,所以 ii 和 jj 都左移一位,让 ii 指向截断的最后一位的位置。要注意的是,如果最后一位是 00 的情况下,jj 此时为 nn,所以为了确保 jj 是合法的,需要加上 j<nj < n 的判断,当 j<nj < n 时,此时 jj 的位置应该是当前 ii 所指的位置值,所以有 arr[j]=arr[i]arr[j] = arr[i],然后 jj 左移一位,如果当前 arr[i]=0arr[i] = 0,那么需要复写一个 00,把当前 arr[j]arr[j] 赋值为 00 后,jj 再左移一位。然后 ii 左移一位,如此往复,直到 ii 退到数组之外,即 i<0i < 0。

/**
 * @param {number[]} arr
 * @return {void} Do not return anything, modify arr in-place instead.
 */
var duplicateZeros = function (arr) {
  const n = arr.length
  let i = 0
  let j = 0
  while (j < n) {
    if (arr[i] == 0) j++
    i++
    j++
  }
  i--
  j--
  while (i >= 0) {
    if (j < n) arr[j] = arr[i]
    j--
    if (arr[i] == 0) {
      arr[j] = 0
      j--
    }
    i--
  }
}
  • 时间复杂度:O(n)O(n),需要遍历数组两次。
  • 空间复杂度:O(1)O(1)
上次更新: 2023/01/31 19:48:05

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 , 转载请注明出处!