问题分析
我们需要处理一个 非严格递增排列 的数组 nums
,目的是删除数组中的重复元素,使得每个元素只出现一次,并返回数组中唯一元素的个数。同时,我们需要保持元素的原始顺序不变。
示例解释
举几个例子来帮助理解:
-
输入:
[1, 1, 2]
输出:
2
,修改后的数组前两个元素是[1, 2]
。 -
输入:
[0, 0, 1, 1, 1, 2, 2, 3, 3, 4]
输出:
5
,修改后的数组前五个元素是[0, 1, 2, 3, 4]
。
C++ 实现
我们将实现一个函数 removeDuplicates
来完成这个任务。以下是这个函数的代码及详细解释:
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
// 处理特殊情况,空数组时直接返回 0
if (nums.empty()) {
return 0;
}
// `index` 用于记录当前要放置唯一元素的位置
int index = 0;
// 从第二个元素开始遍历数组
for (int i = 1; i < nums.size(); ++i) {
// 如果当前元素和前一个元素不同,则是新的唯一元素
if (nums[i] != nums[index]) {
// 将当前元素放置在 `index + 1` 的位置
nums[++index] = nums[i];
}
}
// 返回唯一元素的数量,也就是 `index + 1`
return index + 1;
}
};
代码详解
-
处理特殊情况:
if (nums.empty()) { return 0; }
如果
nums
为空数组,直接返回0
,因为空数组没有任何元素,也没有重复的问题。 -
初始化
index
变量:int index = 0;
index
用来记录当前唯一元素应该放置的位置。初始化为0
表示第一个唯一元素的位置。 -
遍历数组:
for (int i = 1; i < nums.size(); ++i) {
从数组的第二个元素开始遍历,比较当前元素与前一个元素是否相同。
-
判断是否是新的唯一元素:
if (nums[i] != nums[index]) { nums[++index] = nums[i]; }
如果当前元素
nums[i]
与nums[index]
不同,则nums[i]
是新的唯一元素。将它放在index + 1
的位置,并将index
自增。 -
返回结果:
return index + 1;
数组的前
index + 1
个元素是唯一的,返回这个长度作为结果。
示例分析
让我们看一个例子来理解这个算法的工作过程:
输入: [0, 0, 1, 1, 1, 2, 2, 3, 3, 4]
- 初始化:
index = 0
,nums[0] = 0
- 遍历开始:
i = 1
:nums[1] == nums[0]
,继续i = 2
:nums[2] != nums[0]
,nums[++index] = nums[2]
→nums[1] = 1
i = 3
:nums[3] == nums[2]
,继续i = 4
:nums[4] == nums[2]
,继续i = 5
:nums[5] != nums[2]
,nums[++index] = nums[5]
→nums[2] = 2
i = 6
:nums[6] == nums[5]
,继续i = 7
:nums[7] != nums[5]
,nums[++index] = nums[7]
→nums[3] = 3
i = 8
:nums[8] == nums[7]
,继续i = 9
:nums[9] != nums[7]
,nums[++index] = nums[9]
→nums[4] = 4
最终数组变为 [0, 1, 2, 3, 4, 2, 2, 3, 3, 4]
,返回的长度是 5
。
复杂度分析
- 时间复杂度:O(n),其中 n 是数组的长度。我们只遍历了一次数组。
- 空间复杂度:O(1),只使用了常数空间。
结论
这个 removeDuplicates
函数利用了双指针技术来高效地删除重复元素,并保持了数组元素的原始顺序。理解了这个方法后,你可以轻松处理各种类似的数组去重问题。