【LeetCode】80. 删除有序数组中的重复项 II

leetcode

 

在有序数组中原地删除重复元素,使每个元素最多出现两次,可以通过双指针法高效实现。以下是详细实现方法及代码解析:


核心思路:快慢双指针法

  1. 指针定义

    • 快指针(fast)​:遍历数组,探测新元素位置
    • 慢指针(slow)​:标记当前有效数组的末尾位置,确保前 slow 个元素符合条件
  2. 关键逻辑

    • 有序数组中重复元素连续出现,因此只需比较当前元素与慢指针前两位的值
    • 若 nums[fast] != nums[slow-2],说明当前元素未超过两次重复,需保留;否则跳过
  3. 边界处理

    • 数组长度 ≤ 2 时无需处理,直接返回原长度

Go 代码实现

func removeDuplicates(nums []int) int {
    if len(nums) <= 2 {
        return len(nums)
    }
    slow := 2
    for fast := 2; fast < len(nums); fast++ {
        if nums[fast] != nums[slow-2] {
            nums[slow] = nums[fast]
            slow++
        }
    }
    return slow
}

 


代码解析

  1. 初始化

    • slow 从索引 2 开始,因为前两个元素无论是否重复均可保留
  2. 循环遍历

    • 快指针 fast 从 2 开始遍历数组
    • 若 nums[fast] 与 nums[slow-2] 不同,说明当前元素未达到两次重复上限,将其赋值到 nums[slow] 并移动慢指针
  3. 时间复杂度

    • O(n),仅需一次遍历数组
  4. 空间复杂度

    • O(1),未使用额外存储空间

示例验证

  • 输入nums = [1,1,1,2,2,3]
  • 处理过程
    • slow 初始为 2,fast 从 2 开始
    • fast=2nums[2]=1 与 nums[0]=1 相同 → 跳过
    • fast=3nums[3]=2 与 nums[1]=1 不同 → 赋值到 slow=2,此时数组前 3 项为 [1,1,2]
    • 最终 slow=5,数组前 5 项为 [1,1,2,2,3],长度返回 5

对比其他方法

方法优势适用场景
双指针法 时间复杂度 O(n) 有序数组去重
暴力遍历法 逻辑简单 小规模无序数组
哈希表法 支持无序数组去重 需要保留任意次数元素

扩展:允许最多 k 次重复的通用解法

通过参数化允许的最大重复次数 k,可扩展为通用函数:

func removeKDuplicates(nums []int, k int) int {
    if len(nums) <= k {
        return len(nums)
    }
    slow := k
    for fast := k; fast < len(nums); fast++ {
        if nums[fast] != nums[slow-k] {
            nums[slow] = nums[fast]
            slow++
        }
    }
    return slow
}

将 k=2 调用即可适配本题需求。

 


总结

双指针法是解决有序数组去重问题的经典方案,通过合理控制比较逻辑和指针移动规则,既能保证高效性,又满足原地修改的约束条件。此方法在 LeetCode 等算法题中广泛应用,建议深入理解其核心思想以应对类似问题。

posted @ 2025-03-18 15:49  云隙之间  阅读(60)  评论(0)    收藏  举报