文章目录
一、题目要求
给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次
返回删除后数组的 新长度,元素的 相对顺序 应该保持 一致 。
由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。
更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。
将最终结果插入 nums 的前 k 个位置后返回 k 。
不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
判题标准:
系统会用下面的代码来测试你的题解:
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 。不需要考虑数组中超出新长度后面的元素。
提示:
1 <= nums.length <= 3 * 104
-104 <= nums[i] <= 104
nums 已按 升序 排列
二、解题思路
双指针
- 由于当前的 nums 数组为 有序数组,我们需要将该数组中的所有不同的值有且保留一个下来并输出最终数组
- 为此,可以创建 两个位置指针,一个快指针 fast ,一个慢指针 slow
- 对于快指针的作用,是用于遍历 nums 数组的所有值,通过判断 nums[i] 与 nums[i-1] 的值是否为相同值
- 当为相同值时,fast ++
- 当为不同值时,将当前 nums[fast] 的数值赋值给 nums[slow] ,并将 slow++ 和 fast++
- 由此可见,slow 的作用为表示新数组的索引下标和长度
- 所以,slow 只有在找到不重复值时才会 ++ 变动
- 最终输出的新数组的长度即为 slow 的数值,在如下图解中 slow 的返回值为 5
下面为运行流程图解
代码如下:
class Solution
{
public:
int removeDuplicates(vector<int>& nums)
{
// 创建两个位置指针变量,一个慢指针,一个快指针
// 由于需要判断是否存在重复项,故从 1 开始查找
int slow = 1, fast = 1;
// 当 nums 数组为 0 时返回 0 即可
if (nums.size() == 0)
return 0;
// 用快指针循环遍历 nums 数组中的元素
for (;fast<nums.size();fast++)
// 因为是有序数组,判断当前位置和前一位置的数值不相等时,代表为不重复项目
if (nums[fast] != nums[fast-1])
// 将快指针位置的数值存放到慢指针处,并将慢指针++
nums[slow++] = nums[fast];
return slow;
}
};
三、测试结果
-
时间复杂度:O(n),对于遍历 n 个元素的数组一次,每次查找花费 O(1) 的时间。
-
空间复杂度:O(1),并不需要开辟额外的空间,直接采用数值覆盖原数组。