You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

O(1)空间复杂度下有序数组去重问题的排查与优化

解决有序数组原地去重的问题

你的代码在处理奇数次重复元素时失效,核心问题是:当你用pop(i)移除重复元素后,当前i位置被下一个元素填充,但你直接让i递增,跳过了对这个新元素的检查。比如处理[1,1,1]时,第一次pop后数组变成[1,1],i直接变成1,此时i == end,循环终止,剩下的重复元素没被处理。

下面是几种可行的解决技巧:

技巧1:修正现有代码的指针逻辑

把i的递增移到else分支里,只有当前元素和下一个元素不重复时,才让i递增。这样移除重复元素后,i留在原地,继续检查新的当前元素:

def removeDuplicates(nums):
    if not nums:
        return 0
    i = 0
    end = len(nums) - 1
    while i != end:
        if nums[i] == nums[i+1]:
            nums.pop(i)
            end -= 1
        else:
            i += 1
    return len(nums)

测试输入[0,0,1,1,1,2,2,3,3,4],会得到去重后的数组[0,1,2,3,4],返回长度5,完全符合要求。

技巧2:双指针(快慢指针)法(最优解)

这是这类原地去重题的标准高效解法,时间复杂度O(n),空间复杂度O(1),比多次pop操作更高效(pop列表中间元素是O(n)时间,多次操作会拉高整体复杂度)。

思路:用慢指针slow标记去重后数组的最后位置,快指针fast遍历整个数组。当快指针遇到和慢指针不同的元素时,慢指针前进一位,把快指针的元素赋值过去:

def removeDuplicates(nums):
    if not nums:
        return 0
    slow = 0
    for fast in range(1, len(nums)):
        if nums[fast] != nums[slow]:
            slow += 1
            nums[slow] = nums[fast]
    return slow + 1

这个方法不需要删除元素,只是覆盖前面的位置,完全符合“不创建新数组”的要求,不管重复次数是奇数还是偶数都能正确处理。

技巧3:反向遍历删除

从数组末尾开始遍历,删除元素时不会影响前面未遍历元素的索引,避免指针混乱:

def removeDuplicates(nums):
    for i in range(len(nums)-1, 0, -1):
        if nums[i] == nums[i-1]:
            nums.pop(i)
    return len(nums)

反向遍历的好处是,删除当前元素后,前面的元素索引不受影响,遍历过程不会遗漏任何重复情况,逻辑简单易懂。

内容的提问来源于stack exchange,提问作者Rhodey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 02:25:23