|
| 1 | +--- |
| 2 | +title: 80.删除有序数组中的重复项 II:双指针 - C++/Java5 行版 |
| 3 | +date: 2025-02-09 09:08:46 |
| 4 | +tags: [题解, LeetCode, 中等, 数组, 双指针] |
| 5 | +--- |
| 6 | + |
| 7 | +# 【LetMeFly】80.删除有序数组中的重复项 II:双指针 - C++/Java5 行版 |
| 8 | + |
| 9 | +力扣题目链接:[https://leetcode.cn/problems/remove-duplicates-from-sorted-array-ii/](https://leetcode.cn/problems/remove-duplicates-from-sorted-array-ii/) |
| 10 | + |
| 11 | +<p>给你一个有序数组 <code>nums</code> ,请你<strong><a href="http://baike.baidu.com/item/%E5%8E%9F%E5%9C%B0%E7%AE%97%E6%B3%95" target="_blank"> 原地</a></strong> 删除重复出现的元素,使得出现次数超过两次的元素<strong>只出现两次</strong> ,返回删除后数组的新长度。</p> |
| 12 | + |
| 13 | +<p>不要使用额外的数组空间,你必须在 <strong><a href="https://baike.baidu.com/item/%E5%8E%9F%E5%9C%B0%E7%AE%97%E6%B3%95" target="_blank">原地 </a>修改输入数组 </strong>并在使用 O(1) 额外空间的条件下完成。</p> |
| 14 | + |
| 15 | +<p> </p> |
| 16 | + |
| 17 | +<p><strong>说明:</strong></p> |
| 18 | + |
| 19 | +<p>为什么返回数值是整数,但输出的答案是数组呢?</p> |
| 20 | + |
| 21 | +<p>请注意,输入数组是以<strong>「引用」</strong>方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。</p> |
| 22 | + |
| 23 | +<p>你可以想象内部操作如下:</p> |
| 24 | + |
| 25 | +<pre> |
| 26 | +// <strong>nums</strong> 是以“引用”方式传递的。也就是说,不对实参做任何拷贝 |
| 27 | +int len = removeDuplicates(nums); |
| 28 | + |
| 29 | +// 在函数里修改输入数组对于调用者是可见的。 |
| 30 | +// 根据你的函数返回的长度, 它会打印出数组中<strong> 该长度范围内</strong> 的所有元素。 |
| 31 | +for (int i = 0; i < len; i++) { |
| 32 | + print(nums[i]); |
| 33 | +} |
| 34 | +</pre> |
| 35 | + |
| 36 | +<p> </p> |
| 37 | + |
| 38 | +<p><strong>示例 1:</strong></p> |
| 39 | + |
| 40 | +<pre> |
| 41 | +<strong>输入:</strong>nums = [1,1,1,2,2,3] |
| 42 | +<strong>输出:</strong>5, nums = [1,1,2,2,3] |
| 43 | +<strong>解释:</strong>函数应返回新长度 length = <strong><code>5</code></strong>, 并且原数组的前五个元素被修改为 <strong><code>1, 1, 2, 2, 3</code></strong>。 不需要考虑数组中超出新长度后面的元素。 |
| 44 | +</pre> |
| 45 | + |
| 46 | +<p><strong>示例 2:</strong></p> |
| 47 | + |
| 48 | +<pre> |
| 49 | +<strong>输入:</strong>nums = [0,0,1,1,1,1,2,3,3] |
| 50 | +<strong>输出:</strong>7, nums = [0,0,1,1,2,3,3] |
| 51 | +<strong>解释:</strong>函数应返回新长度 length = <strong><code>7</code></strong>, 并且原数组的前七个元素被修改为 <strong><code>0, 0, 1, 1, 2, 3, 3</code></strong>。不需要考虑数组中超出新长度后面的元素。 |
| 52 | +</pre> |
| 53 | + |
| 54 | +<p> </p> |
| 55 | + |
| 56 | +<p><strong>提示:</strong></p> |
| 57 | + |
| 58 | +<ul> |
| 59 | + <li><code>1 <= nums.length <= 3 * 10<sup>4</sup></code></li> |
| 60 | + <li><code>-10<sup>4</sup> <= nums[i] <= 10<sup>4</sup></code></li> |
| 61 | + <li><code>nums</code> 已按升序排列</li> |
| 62 | +</ul> |
| 63 | + |
| 64 | + |
| 65 | + |
| 66 | +## 解题方法一:快慢指针 |
| 67 | + |
| 68 | +使用一个慢指针指向数组中已经合法的元素(初始值为1,因为前两个元素必合法),使用一个快指针指向当前遍历到的元素。 |
| 69 | + |
| 70 | +快指针从下标`2`开始遍历,如果快指针指向元素和慢指针指向元素的前一个元素不同,则快指针指向元素可以合法地加入数组(慢指针右移一位,快指针元素放到慢指针位置)。 |
| 71 | + |
| 72 | ++ 时间复杂度$O(len(nums))$ |
| 73 | ++ 空间复杂度$O(1)$ |
| 74 | + |
| 75 | +### AC代码 |
| 76 | + |
| 77 | +#### C++ |
| 78 | + |
| 79 | +```cpp |
| 80 | +/* |
| 81 | + * @Author: LetMeFly |
| 82 | + * @Date: 2025-02-09 08:44:41 |
| 83 | + * @LastEditors: LetMeFly.xyz |
| 84 | + * @LastEditTime: 2025-02-09 08:48:30 |
| 85 | + */ |
| 86 | +class Solution { |
| 87 | +public: |
| 88 | + int removeDuplicates(vector<int>& nums) { |
| 89 | + int slow = 1; |
| 90 | + for (int fast = 2; fast < nums.size(); fast++) { |
| 91 | + if (nums[fast] != nums[slow - 1]) { |
| 92 | + nums[++slow] = nums[fast]; |
| 93 | + } |
| 94 | + } |
| 95 | + return min((int)nums.size(), slow + 1); |
| 96 | + } |
| 97 | +}; |
| 98 | +``` |
| 99 | +
|
| 100 | +#### Python |
| 101 | +
|
| 102 | +```python |
| 103 | +''' |
| 104 | +Author: LetMeFly |
| 105 | +Date: 2025-02-09 08:53:38 |
| 106 | +LastEditors: LetMeFly.xyz |
| 107 | +LastEditTime: 2025-02-09 08:55:23 |
| 108 | +''' |
| 109 | +from typing import List |
| 110 | +
|
| 111 | +class Solution: |
| 112 | + def removeDuplicates(self, nums: List[int]) -> int: |
| 113 | + slow = 1 |
| 114 | + for fast in range(2, len(nums)): |
| 115 | + if nums[fast] != nums[slow - 1]: |
| 116 | + slow += 1 |
| 117 | + nums[slow] = nums[fast] |
| 118 | + return min(len(nums), slow + 1) |
| 119 | +``` |
| 120 | + |
| 121 | +#### Java |
| 122 | + |
| 123 | +```java |
| 124 | +/* |
| 125 | + * @Author: LetMeFly |
| 126 | + * @Date: 2025-02-09 08:53:42 |
| 127 | + * @LastEditors: LetMeFly.xyz |
| 128 | + * @LastEditTime: 2025-02-09 08:58:07 |
| 129 | + */ |
| 130 | +class Solution { |
| 131 | + public int removeDuplicates(int[] nums) { |
| 132 | + int slow = 1; |
| 133 | + for (int fast = 2; fast < nums.length; fast++) { |
| 134 | + if (nums[fast] != nums[slow - 1]) { |
| 135 | + nums[++slow] = nums[fast]; |
| 136 | + } |
| 137 | + } |
| 138 | + return Math.min(slow + 1, nums.length); |
| 139 | + } |
| 140 | +} |
| 141 | +``` |
| 142 | + |
| 143 | +#### Go |
| 144 | + |
| 145 | +```go |
| 146 | +/* |
| 147 | + * @Author: LetMeFly |
| 148 | + * @Date: 2025-02-09 08:53:44 |
| 149 | + * @LastEditors: LetMeFly.xyz |
| 150 | + * @LastEditTime: 2025-02-09 09:00:09 |
| 151 | + */ |
| 152 | +package main |
| 153 | + |
| 154 | +func removeDuplicates(nums []int) int { |
| 155 | + slow := 1 |
| 156 | + for fast := 2; fast < len(nums); fast++ { |
| 157 | + if nums[fast] != nums[slow - 1] { |
| 158 | + slow++ |
| 159 | + nums[slow] = nums[fast] |
| 160 | + } |
| 161 | + } |
| 162 | + return min(slow + 1, len(nums)) |
| 163 | +} |
| 164 | +``` |
| 165 | + |
| 166 | +## 解题方法二:易想版本 |
| 167 | + |
| 168 | +> 来[自](https://github.com/LetMeFly666/LeetCode/blob/64231493342ec7c9a18147c5f32d4e6211df7e33/Codes/0080-remove-duplicates-from-sorted-array-ii.cpp)2022.6.19,当时就想[写题解](https://github.com/LetMeFly666/LeetCode/blob/64231493342ec7c9a18147c5f32d4e6211df7e33/Codes/0080-remove-duplicates-from-sorted-array-ii.cpp#L11)了。 |
| 169 | + |
| 170 | +如果[方法一](#解题方法一快慢指针)难想怎么办?很简单,使用两个指针指向“相同连续元素”的始末位置总可以了吧。 |
| 171 | + |
| 172 | +每次得到一种元素的始末位置后,就放置`min(2, 这种元素个数)`个这种元素到“合法数组”中就好了。 |
| 173 | + |
| 174 | ++ 时间复杂度$O(len(nums))$ |
| 175 | ++ 空间复杂度$O(1)$ |
| 176 | + |
| 177 | +### [AC](https://github.com/LetMeFly666/LeetCode/blob/64231493342ec7c9a18147c5f32d4e6211df7e33/Codes/0080-remove-duplicates-from-sorted-array-ii.cpp#L1-L6)[代码](https://github.com/LetMeFly666/LeetCode/blob/64231493342ec7c9a18147c5f32d4e6211df7e33/Codes/0080-remove-duplicates-from-sorted-array-ii.cpp#L42-L58) |
| 178 | + |
| 179 | +#### C++ |
| 180 | + |
| 181 | +```cpp |
| 182 | +/* |
| 183 | + * @Author: LetMeFly |
| 184 | + * @Date: 2022-06-19 09:51:38 |
| 185 | + * @LastEditors: LetMeFly |
| 186 | + * @LastEditTime: 2022-06-19 10:31:22 |
| 187 | + */ |
| 188 | + |
| 189 | +class Solution { |
| 190 | +public: |
| 191 | + int removeDuplicates(vector<int>& nums) { |
| 192 | + int cnt = 0; |
| 193 | + int l = 0, r = 1; // [l, r)相同 |
| 194 | + nums.push_back(1e5); |
| 195 | + for (; r < nums.size(); r++) { |
| 196 | + if (nums[r] != nums[l]) { |
| 197 | + for (int i = 0; i < min(2, r - l); i++) { |
| 198 | + nums[cnt++] = nums[r - 1]; |
| 199 | + } |
| 200 | + l = r; |
| 201 | + } |
| 202 | + } |
| 203 | + return cnt; |
| 204 | + } |
| 205 | +}; |
| 206 | +``` |
| 207 | +
|
| 208 | +## End |
| 209 | +
|
| 210 | +> 同步发文于[CSDN](https://letmefly.blog.csdn.net/article/details/145528267)和我的[个人博客](https://blog.letmefly.xyz/),原创不易,转载经作者同意后请附上[原文链接](https://blog.letmefly.xyz/2025/02/09/LeetCode%200080.%E5%88%A0%E9%99%A4%E6%9C%89%E5%BA%8F%E6%95%B0%E7%BB%84%E4%B8%AD%E7%9A%84%E9%87%8D%E5%A4%8D%E9%A1%B9II/)哦~ |
| 211 | +> |
| 212 | +> 千篇源码题解[已开源](https://github.com/LetMeFly666/LeetCode) |
| 213 | +> |
| 214 | +> Tisfy:[https://blog.letmefly.xyz/2025/02/09/LeetCode 0080.删除有序数组中的重复项II](https://blog.letmefly.xyz/2025/02/09/LeetCode%200080.%E5%88%A0%E9%99%A4%E6%9C%89%E5%BA%8F%E6%95%B0%E7%BB%84%E4%B8%AD%E7%9A%84%E9%87%8D%E5%A4%8D%E9%A1%B9II/) |
0 commit comments