Skip to content

Files

Latest commit

c29b144 · May 17, 2024

History

History
This branch is 1 commit ahead of, 1175 commits behind doocs/leetcode:main.

0080.Remove Duplicates from Sorted Array II

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
May 17, 2024
May 17, 2024
Apr 10, 2023
Jan 13, 2024
Apr 10, 2023
Apr 10, 2023
Apr 10, 2023
Apr 10, 2023
Nov 9, 2023
Apr 18, 2023
comments difficulty edit_url tags
true
中等
数组
双指针

English Version

题目描述

给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使得出现次数超过两次的元素只出现两次 ,返回删除后数组的新长度。

不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

 

说明:

为什么返回数值是整数,但输出的答案是数组呢?

请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。

你可以想象内部操作如下:

// nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝
int len = removeDuplicates(nums);

// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。
for (int i = 0; i < len; i++) {
    print(nums[i]);
}

 

示例 1:

输入:nums = [1,1,1,2,2,3]
输出:5, nums = [1,1,2,2,3]
解释:函数应返回新长度 length = 5, 并且原数组的前五个元素被修改为 1, 1, 2, 2, 3。 不需要考虑数组中超出新长度后面的元素。

示例 2:

输入:nums = [0,0,1,1,1,1,2,3,3]
输出:7, nums = [0,0,1,1,2,3,3]
解释:函数应返回新长度 length = 7, 并且原数组的前七个元素被修改为 0, 0, 1, 1, 2, 3, 3。不需要考虑数组中超出新长度后面的元素。

 

提示:

  • 1 <= nums.length <= 3 * 104
  • -104 <= nums[i] <= 104
  • nums 已按升序排列

解法

方法一:一次遍历

我们用一个变量 k 记录当前已经处理好的数组的长度,初始时 k = 0 ,表示空数组。

然后我们从左到右遍历数组,对于遍历到的每个元素 x ,如果 k < 2 或者 x n u m s [ k 2 ] ,我们就将 x 放到 n u m s [ k ] 的位置,然后 k 自增 1 。否则,$x$ 与 n u m s [ k 2 ] 相同,我们直接跳过这个元素。继续遍历,直到遍历完整个数组。

这样,当遍历结束时,$nums$ 中前 k 个元素就是我们要求的答案,且 k 就是答案的长度。

时间复杂度 O ( n ) ,空间复杂度 O ( 1 ) 。其中 n 为数组的长度。

补充:

原问题要求最多相同的数字最多出现 2 次,我们可以扩展至相同的数字最多保留 k 个。

  • 由于相同的数字最多保留 k 个,那么原数组的前 k 个元素我们可以直接保留;
  • 对于后面的数字,能够保留的前提是:当前数字 x 与前面已保留的数字的倒数第 k 个元素比较,不同则保留,相同则跳过。

相似题目:

Python3

class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        k = 0
        for x in nums:
            if k < 2 or x != nums[k - 2]:
                nums[k] = x
                k += 1
        return k

Java

class Solution {
    public int removeDuplicates(int[] nums) {
        int k = 0;
        for (int x : nums) {
            if (k < 2 || x != nums[k - 2]) {
                nums[k++] = x;
            }
        }
        return k;
    }
}

C++

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        int k = 0;
        for (int x : nums) {
            if (k < 2 || x != nums[k - 2]) {
                nums[k++] = x;
            }
        }
        return k;
    }
};

Go

func removeDuplicates(nums []int) int {
	k := 0
	for _, x := range nums {
		if k < 2 || x != nums[k-2] {
			nums[k] = x
			k++
		}
	}
	return k
}

TypeScript

function removeDuplicates(nums: number[]): number {
    let k = 0;
    for (const x of nums) {
        if (k < 2 || x !== nums[k - 2]) {
            nums[k++] = x;
        }
    }
    return k;
}

Rust

impl Solution {
    pub fn remove_duplicates(nums: &mut Vec<i32>) -> i32 {
        let mut k = 0;
        for i in 0..nums.len() {
            if k < 2 || nums[i] != nums[k - 2] {
                nums[k] = nums[i];
                k += 1;
            }
        }
        k as i32
    }
}

JavaScript

/**
 * @param {number[]} nums
 * @return {number}
 */
var removeDuplicates = function (nums) {
    let k = 0;
    for (const x of nums) {
        if (k < 2 || x !== nums[k - 2]) {
            nums[k++] = x;
        }
    }
    return k;
};

C#

public class Solution {
    public int RemoveDuplicates(int[] nums) {
        int k = 0;
        foreach (int x in nums) {
            if (k < 2 || x != nums[k - 2]) {
                nums[k++] = x;
            }
        }
        return k;
    }
}