leetcode打卡-0080删除有序数组中的重复项II
题目描述
给你一个有序数组nums,请你原地删除重复出现的元素,使每个元素最多出现两次,返回删除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用O(1)额外空间的条件下完成。
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array-ii
解题思路
1. 通用套路
这题和leetcode第26题-删除数组中重复数,几乎一样的思路,26题是只保留1个,此题是保留2个,已经在这里记录过题解。
- 由于是保留2个相同数字,对于前2个数字,我们可以直接保留。
- 对于后面的任意数字,能够保留的前提是:与当前写入的位置前面的第2个元素进行比较,不相同则保留。
将问题衍生至保留k个数字,则可以扩展为:
在有序数组的前k个元素里,每种数字都会符合不超过k个的条件;反向思考,一个数字与写入位置的第前k个元素对比,如果相同,证明写入位置之前已经写满了k个当前元素,那么写入位置就需要寻找一个新元素写入了,如果不同,就把当前元素复制过去补位。
所以,通用的Python实现代码如下:
def process(nums, k):
# idx记录最初的写入位置,直接保留了前k位
idx = k
# 从第k位往后遍历,判断是否满足上面的第二条推定
for x in nums[k:]:
if nums[idx-k] != x:
nums[idx] = x
idx += 1
return idx
- 时间复杂度O(n)
- 空间复杂度O(1)
那么这题的题解就可以写成:
# Python3实现
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
idx = 2
for x in nums[2:]:
if nums[idx-2] != x:
nums[idx] = x
idx += 1
return idx
练习一下Rust
impl Solution {
pub fn remove_duplicates(nums: &mut Vec<i32>) -> i32 {
if nums.is_empty() {
return 0;
}
if nums.len() <= 2 {
return nums.len() as i32;
}
let mut i = 2;
for j in 2..nums.len() {
if nums[i-2] != nums[j] {
nums[i] = nums[j];
i += 1;
}
}
i as i32
}
}
总结
参考之前的题解,注意总结顺序遍历中“保留逻辑”的套路。