给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。
考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过:
更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。
返回 k 。
判题标准:
系统会用下面的代码来测试你的题解:
int[] nums = […]; // 输入数组
int[] expectedNums = […]; // 长度正确的期望答案
int k = removeDuplicates(nums); // 调用
assert k == expectedNums.length;
for (int i = 0; i < k; i++) {
assert nums[i] == expectedNums[i];
}
如果所有断言都通过,那么您的题解将被 通过。
示例 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 。不需要考虑数组中超出新长度后面的元素。
解答:用快慢指针解决
func removeDuplicates(nums []int) int {
// 特殊情况:当数组长度为1时,此时不重复元素长度为1
if len(nums) == 1 {
return 1
}
// 在数组首部添加两个快慢指针,慢指针指向0,快指针指向1
// 慢指针负责存储不重复元素(慢指针及其左侧都是不重复元素),快指针负责寻找不重复元素
slow := 0
fast := 1
// 在快指针越过数组边界之前向前寻找不重复元素,判断快指针找到的元素nums[fast]与慢指针元素nums[slow]是否相等:
for fast < len(nums) {
if nums[slow] != nums[fast] {
// 不相等,说明找到了新的不重复元素
// slow向右移动一位来存储该不重复元素
slow++
// 将该nums[fast]值更新到nums[slow]中
// 优化:如果slow和fast紧挨着,比如数组中不存在重复元素,则slow+1和fast就是同一个,此时的赋值操作是不必要的;因此可以判断fast-slow>1时才进行赋值
nums[slow],nums[fast] = nums[fast],nums[slow]
// fast继续向后寻找
fast++
} else {
// 相等,说明是重复元素,跳过,fast继续向后寻找
fast++
}
}
// 当fast越界,此时慢指针slow的位置就是前面不重复数组部分的最后一个元素的索引
return slow + 1
}