题目
给定一个增序排列数组 nums ,你需要在 原地 删除重复出现的元素,使得每个元素最多出现两次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
思路-O(n^2)
和删除排序数组中的重复项思路相似,加入计数器判断元素是否出现了2次。
class Solution {public int removeDuplicates(int[] nums) {int count = 0; // 计数器int i = 0;int removed = 0;while (i + removed < nums.length - 1) {if (nums[i] != nums[i + 1]) { // 相邻数不一样,计数器清零i++;count = 0;} else {count++; // 相邻数一样,计数器+1if (count < 2) { // 已经出现次数小于2次,放过i++;} else { // 已经出现了2次,这次是第3次,删除removeOne(nums, i + 1);removed++;}}}return nums.length - removed;}public void removeOne(int[] nums, int i) {for (int k = i; k < nums.length - 1; k++) {nums[k] = nums[k + 1];}}}
思路-O(n)
示例: nums = [1, 2, 3, 4, 4, 4, 5]
slow和fast指针在遇到第三个4(也就是nums[5]) 之前, nums[slow] = nums[fast] 一直是无效的交换。因为fast和slow的值是相等的,nums[slow - 2] != nums[fast] 一直都是true,所以每次while loop的时候 slow和fast都会++,它们的初始值又都是2。
slow和fast指针在遇到第三个4(也就是nums[5]) 的时候,这时候就需要将nums[6]换到nums[5],也就是说,fast需要比slow快1个位置。if(nums[slow - 2] != nums[fast]) 不会运行,就使得fast++但是slow没有++。
总结一下:
如果 slow的第前两个数 不等于 fast的数:
情况一:slow的数 等于 fast的数
slow 和 fast 原地无效交换
slow++;fast++;
情况二:slow的数 不等于 fast的数
slow 和 fast 有效交换 (因为slow和fast指向的数不同)
slow++;fast++;
如果 slow的第前两个数 等于 fast的数:
此时说明slow位置需要被替换,替换的前提是fast要跑到slow的前面去,
所以fast++, slow原地不动
class Solution {public int removeDuplicates(int[] nums) {if (nums.length <= 2) { // 长度小于3,不可能有重复项大于2次的元素,直接返回return nums.length;}int slow = 2;int fast = 2;while (fast < nums.length) {if (nums[slow - 2] != nums[fast]) {nums[slow] = nums[fast];slow++;}fast++;}return slow;}}
