100 - 删除排序数组中的重复数字

本文介绍了一种不使用额外空间删除数组中重复元素的方法。通过遍历数组并利用原数组进行覆盖来实现,确保最终返回的新数组长度正确且不包含重复项。

5.2

题目要求是不许使用额外的空间。

所以这样写就是错误的了 :nums = Arrays.copyOf(nums, nums.length-1); 这是建立了新的数组。

直接标记length 的长度就可以了。

这个题是不需要重新维护数组的。

public class Solution {
    /**
     * @param A: a array of integers
     * @return : return an integer
     */
    public int removeDuplicates(int[] nums) {
        // write your code here
        int length = nums.length;
        if(length <= 1){
            return length;
        }
        int i = 0;
        for(i = 0; i < length - 1; i++){
            while(i < length -1 && nums[i] == nums[i+1]){
                for(int j = i+1;j < length-1;j++){
                    nums[j] = nums[j+1];
                }
                length --;
                //nums = Arrays.copyOf(nums, nums.length-1);
                //System.out.println(Arrays.toString(nums));
            }
        }
        
        return length ;
    }
}


<think>好的,用户想了解如何使用双指针法删除数组中的重复数字。首先,我得回忆一下双指针法的基本思想。双指针法通常在数组或链表操作中用于减少时间复杂度,特别是处理元素覆盖或顺序调整的问题。 那删除重复元素的话,通常要求原地修改,也就是不使用额外的空间或者使用O(1)的空间。比如LeetCode上的经典题目“删除有序数组中的重复项”。这时候双指针法应该是适用的。 接下来,我需要确定双指针的具体用法。一般来说,会有一个快指针和一个慢指针。快指针用于遍历整个数组,而慢指针则指向下一个非重复元素应该存放的位置。这样,每当快指针发现一个不重复的元素时,就将其复制到慢指针的位置,然后慢指针前进一步。 比如,对于数组[1,1,2],快指针开始于索引1,慢指针在索引0。当快指针发现元素与慢指针不同时,就将该元素复制到慢指针的下一个位置,然后慢指针移动。这样,最后慢指针的位置+1就是新数组的长度。 不过,用户的问题中没有明确数组是否有序。如果是无序数组,可能需要先排序,但这样会改变原数组的顺序。如果题目要求保持原顺序,但删除重复项,可能需要另一种方法。但通常情况下,双指针法用于有序数组的情况,因为无序的话重复项可能出现在任何地方,处理起来复杂度更高。所以假设用户的问题中的数组是有序的,这样双指针法更有效。 然后,我需要考虑具体步骤。首先判断数组是否为空,如果是的话直接返回0。然后初始化慢指针在0的位置,快指针从1开始遍历。当快指针的元素不等于慢指针的元素时,慢指针先加一,然后赋值,快指针继续。最后返回慢指针+1作为新长度。 同时,需要注意边界条件,比如数组长度为0或1的情况,这时候不需要处理。 然后,用户可能需要一个例子来理解这个过程。例如,数组[0,0,1,1,1,2,2,3,3,4],应用双指针法后,慢指针最后会停在索引4的位置,对应的元素是4,所以新数组长度是5,数组前五个元素是0,1,2,3,4。 另外,要确保代码实现正确。比如在Python中,数组可以通过指针操作覆盖元素,最终返回长度即可。需要注意在赋值时的顺序,先移动慢指针再赋值,避免覆盖错误。 可能用户还会有疑问,比如为什么可以这样做?因为数组是有序的,重复的元素必然是连续的,所以只要比较快指针和慢指针的元素是否相同,就可以确定是否需要保留当前元素。 总结下来,步骤是:初始化两个指针,快指针遍历,慢指针记录非重复位置,每次发现不同元素就移动慢指针并赋值,最后返回长度。这样时间复杂度是O(n),空间是O(1)。</think>### 双指针法删除数组重复数字分步详解 #### 一、适用条件 1. **有序数组**(若数组无序需先排序,但会改变原始顺序) 2. **原地修改**(空间复杂度 $O(1)$) #### 二、算法原理 - **快指针**:遍历数组,寻找新元素 - **慢指针**:标记唯一元素应插入的位置 #### 三、具体步骤(以数组 `[0,0,1,1,1,2,2,3,3,4]` 为例) 1. **初始化指针** - 慢指针 `slow = 0` - 快指针 `fast = 1` - 初始状态:`[0,0,1,1,1,2,2,3,3,4]` ↑ ↑ slow fast 2. **遍历过程** - `fast=1`:`nums[fast] = nums[slow]`,跳过 - `fast=2`:`nums[fast] ≠ nums[slow]` - `slow += 1` → `slow=1` - `nums[slow] = nums[fast]` → `[0,1,1,1,1,2,2,3,3,4]` ↑ ↑ slow fast 3. **继续遍历** - `fast=3~4`:重复值,跳过 - `fast=5`:`nums[fast]=2 ≠ nums[slow]=1` - `slow +=1` → `slow=2` - 赋值 → `[0,1,2,1,1,2,2,3,3,4]` ↑ ↑ slow fast 4. **最终结果** - 遍历完成后,`slow=4`,返回长度 `slow+1=5` -数组前5位:`[0,1,2,3,4]` #### 四、代码实现(Python) ```python 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 ``` #### 五、复杂度分析 1. **时间复杂度**:$O(n)$,仅遍历一次数组 2. **空间复杂度**:$O(1)$,仅使用常量空间 #### 六、关键点总结 - **有序性保障**:确保重复元素连续 - **指针移动条件**:仅当快指针发现新唯一值时移动慢指针 - **覆盖策略**:直接修改原数组前部内容,避免额外空间 #### 七、扩展思考 若数组无序且要求保持原始顺序,可通过哈希表记录已出现元素(空间复杂度 $O(n)$),或先排序再使用双指针法(时间复杂度 $O(n \log n)$)。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值