|
| 1 | +# [1089. 复写零](https://leetcode.cn/problems/duplicate-zeros/) |
| 2 | + |
| 3 | +- 标签:数组、双指针 |
| 4 | +- 难度:简单 |
| 5 | + |
| 6 | +## 题目大意 |
| 7 | + |
| 8 | +**描述**:给定搞一个长度固定的整数数组 $arr$。 |
| 9 | + |
| 10 | +**要求**:键改改数组中出现的每一个 0ドル$ 都复写一遍,并将其余的元素向右平移。 |
| 11 | + |
| 12 | +**说明**: |
| 13 | + |
| 14 | +- 注意:不要在超过该数组长度的位置写上元素。请对输入的数组就地进行上述修改,不要从函数返回任何东西。 |
| 15 | +- 1ドル \le arr.length \le 10^4$。 |
| 16 | +- 0ドル \le arr[i] \le 9$。 |
| 17 | + |
| 18 | +**示例**: |
| 19 | + |
| 20 | +- 示例 1: |
| 21 | + |
| 22 | +```Python |
| 23 | +输入:arr = [1,0,2,3,0,4,5,0] |
| 24 | +输出:[1,0,0,2,3,0,0,4] |
| 25 | +解释:调用函数后,输入的数组将被修改为:[1,0,0,2,3,0,0,4] |
| 26 | +``` |
| 27 | + |
| 28 | +- 示例 2: |
| 29 | + |
| 30 | +```Python |
| 31 | +输入:arr = [1,2,3] |
| 32 | +输出:[1,2,3] |
| 33 | +解释:调用函数后,输入的数组将被修改为:[1,2,3] |
| 34 | +``` |
| 35 | + |
| 36 | +## 解题思路 |
| 37 | + |
| 38 | +### 思路 1:两次遍历 + 快慢指针 |
| 39 | + |
| 40 | +因为数组中出现的 0ドル$ 需要复写为 00ドル,ドル占用空间从一个单位变成两个单位空间,那么右侧必定会有一部分元素丢失。我们可以先遍历一遍数组,找出复写后需要保留的有效数字部分与需要丢失部分的分界点。则从分界点开始,分界点右侧的元素都可以丢失。 |
| 41 | + |
| 42 | +我们再次逆序遍历数组, |
| 43 | + |
| 44 | +1. 使用两个指针 $slow$、$fast,ドル$slow$ 表示当前有效字符位置,$fast$ 表示当前遍历字符位置。一开始 $slow$ 和 $fast$ 都指向数组开始位置。 |
| 45 | +2. 正序扫描数组: |
| 46 | + 1. 如果遇到 $arr[slow] == 0,ドル则让 $fast$ 指针多走一步。 |
| 47 | + 2. 然后 $fast$、$slow$ 各自向右移动 1ドル$ 位,直到 $fast$ 指针移动到数组末尾。此时 $slow$ 左侧数字 $arr[0]... arr[slow - 1]$ 为需要保留的有效数字部分, $arr[slow]...arr[fast - 1]$ 为需要丢失部分。 |
| 48 | +3. 令 $slow$、$fast$ 分别左移 1ドル$ 位,此时 $slow$ 指向最后一个有效数字,$fast$ 指向丢失部分的最后一个数字。此时 $fast$ 可能等于 $size - 1,ドル也可能等于 $size$(比如输入 $[0, 0, 0]$)。 |
| 49 | +4. 逆序遍历数组: |
| 50 | + 1. 将 $slow$ 位置元素移动到 $fast$ 位置。 |
| 51 | + 2. 如果遇到 $arr[slow] == 0,ドル则令 $fast$ 减 1ドル,ドル然后再复制 1ドル$ 个 0ドル$ 到 $fast$ 位置。 |
| 52 | + 3. 令 $slow$、$fast$ 分别左移 1ドル$ 位。 |
| 53 | + |
| 54 | +### 思路 1:代码 |
| 55 | + |
| 56 | +```Python |
| 57 | +class Solution: |
| 58 | + def duplicateZeros(self, arr: List[int]) -> None: |
| 59 | + """ |
| 60 | + Do not return anything, modify arr in-place instead. |
| 61 | + """ |
| 62 | + size = len(arr) |
| 63 | + slow, fast = 0, 0 |
| 64 | + while fast < size: |
| 65 | + if arr[slow] == 0: |
| 66 | + fast += 1 |
| 67 | + slow += 1 |
| 68 | + fast += 1 |
| 69 | + |
| 70 | + slow -= 1 # slow 指向最后一个有效数字 |
| 71 | + fast -= 1 # fast 指向丢失部分的最后一个数字(可能在减 1 之后为 size,比如输入 [0, 0, 0]) |
| 72 | + |
| 73 | + while slow >= 0: |
| 74 | + if fast < size: # 防止 fast 越界 |
| 75 | + arr[fast] = arr[slow] # 将 slow 位置元素移动到 fast 位置 |
| 76 | + if arr[slow] == 0 and fast >= 0: # 遇见 0 则复制 0 到 fast - 1 位置 |
| 77 | + fast -= 1 |
| 78 | + arr[fast] = arr[slow] |
| 79 | + fast -= 1 |
| 80 | + slow -= 1 |
| 81 | +``` |
| 82 | + |
| 83 | +### 思路 1:复杂度分析 |
| 84 | + |
| 85 | +- **时间复杂度**:$O(n),ドル其中 $n$ 为数组 $arr$ 中的元素个数。 |
| 86 | +- **空间复杂度**:$O(1)$。 |
0 commit comments