3.删除有序数组中的重复项
题目
给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。
考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过:
更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。 返回 k 。
示例 1:
输入:nums = [1,1,2]
输出:2, nums = [1,2,_]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。
示例 2:
输入:nums = [0,0,1,1,1,2,2,3,3,4]
输出:5, nums = [0,1,2,3,4]
解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。
思路
双指针
- 既然非严格递增队列,那么重复的元素一定会相邻,那我们可以从0开始遍历,将没有重复的数值替换放到数组的开头
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
# 第一个位置的不用判断
k = 1
for i in range(len(nums)):
# 当前的数值与已放置的数值不同就重新放置
if nums[i] != nums[k - 1]:
nums[k] = nums[i]
k += 1
return k
class Solution {
fun removeDuplicates(nums: IntArray): Int {
var k = 1
for(i in nums){
if (i != nums[k - 1]) {
nums[k] = i
k ++
}
}
return k
}
}
优化:
假如数组是[0, 1, 2, 3, 4, 5] 此时数组中没有重复元素,按照上面的方法,每次比较时nums[i]都不等于nums[k - 1],因此就会将k指向的元素原地复制一遍,这个操作其实是不必要的。
优化的核心思想是:只有当当前索引 i 和写入位置 k 不相等时,才进行复制操作。
所以优化就是:只有当 i > k 时才写入
def removeDuplicates(self, nums: List[int]) -> int:
k = 1
for i in range(len(nums)):
if nums[i] != nums[k - 1]:
if i > k:
nums[k] = nums[i]
k += 1
return k
一定要注意: 这里比较的是 nums[i] != nums[k -1], 而不能是i - 1。
因为i中的元素会被后面的覆盖掉,会变。 比较i - 1是不对的,而k - 1才是去重后的真实结果。
- 邮箱 :charon.chui@gmail.com
- Good Luck!