一、题目
26. 删除有序数组中的重复项 - 力扣(LeetCode) 给你一个 非严格递增排列 的数组 nums
,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums
中唯一元素的个数。 考虑 nums
的唯一元素的数量为 k
,你需要做以下事情确保你的题解可以被通过:
更改数组 nums
,使 nums
的前 k
个元素包含唯一元素,并按照它们最初在 nums
中出现的顺序排列。nums
的其余元素与 nums
的大小不重要。 返回 k
。
二、思路
数组题用循环解,要删除元素肯定涉及把后面的元素与前面的元素交换,涉及到交换肯定是双指针,由此得出应该维护双指针加循环 求解; 刚开始是这么个思路,敲了个例子给自己看: // 初始数组 : 1 1 2 3 4 4 4
设想应该双指针同时从左到右,每轮循环维护一个值用来存慢指针指向的值,当快指针的值遍历到不等于慢指针的值时就交换位置,带着这个想法就敲下了代码: int slow = 0;
for (int fast = 1; fast < len; fast++) {
int tmp = nums[left];
if (nums[fast] != tmp) {
nums[++slow] = nums[fast];
}
}
然后马上就出现了问题:使用 nums[fast] != tmp 来比较的话相当于没换,又给他换回来了,于是想了想,一拍脑袋:这数组是一个非严格递增 的数组,越到后面元素越大,校验时用 > 不就好了嘛,当 nums[fast] <= tmp 时即可视为目前慢指针往后快指针往前全是重复值 (这里想一下为什么),遂解出解法一 ; 下一题穿越回来:解法二 ,请;
三、解法
解法一
class Solution {
public int removeDuplicates(int[] nums) {
int len = nums.length;
if (len <= 2) {
return len;
}
int slow = 0;
for (int fast = 1; fast < len; fast++) {
int tmp = nums[slow];
if (nums[fast] > tmp) {
nums[++slow] = nums[fast++];
}
}
return slow + 1;
}
}
解法二
class Solution {
public int removeDuplicates(int[] nums) {
return handle(nums, 1);
}
public int handle(int[] nums, int k) {
int len = nums.length;
// e.g. 允许相同元素重复3次
// 数组长度都不到3,没有检验的意义
if (len < k) {
return len;
}
// 配合例子食用:
// 0 0 <<1>> 1 1 2 2 3 3 4
// ...
// 0 0 1 1 <<1>> 2 2 3 3 4
// 0 0 1 1 <1> <2> 2 3 3 4
// 0 0 1 1 <2> <2> 2 3 3 4
// 0 0 1 1 2 <2> <2> 3 3 4
// 0 0 1 1 2 2 <2> <3> 3 4
// 0 0 1 1 2 2 <3> <3> 3 4
// ...
int slow = k, fast = k;
while (fast < len) {
if (nums[fast] > nums[slow - k]) {
nums[slow++] = nums[fast];
}
fast++;
}
return slow;
}
}