标签搜索

目 录CONTENT

文章目录

去除有序数组/链表的重复元素--双指针原地修改.md

小小城
2021-08-22 / 0 评论 / 0 点赞 / 4 阅读 / 987 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2022-05-02,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

去除有序数组的重复元素--双指针原地修改

@[toc]

一、题目描述

在这里插入图片描述

二、分析

  •  显然,由于数组已经排序,所以重复的元素一定连在一起,找出它们并不难,但如果毎找到一个重复元素就立即删除它,就是在数组中间进行删除操作,整个时间复杂度是会达到O(N^2)。而且题目要求我们原地修改,也就是说不能用辅助数组,空间复杂度得是 O(1)。
  •  其实,对于数组相关的算法问题,有一个通用的技巧:要尽量避免在中间删除元素,那我就想先办法把这个元素换到最后去。这样的话,最终待删除的元素都拖在数组尾部,一个一个 pop 掉就行了,每次操作的时间复杂度也就降低到 O(1) 了。
  •  按照这个思路呢,又可以衍生出解决类似需求的通用方式:双指针技巧。具体一点说,应该是快慢指针。
  •  我们 让慢指针 slow 走左后面,快指针 fast 走在前面探路,找到一个不重复的元素就告诉 slow 并让 slow 前进一步。这样当 fast 指针遍历完整个数组 nums 后,nums[0..slow] 就是不重复元素,之后的所有元素都是重复元素

三、代码:数组

int removeDuplicates(int[] nums) 
{
    int n = nums.length;
    if (n == 0) 
    	return 0;
    
    int slow = 0, fast = 1;
    
    while (fast < n) 
    {
        if (nums[fast] != nums[slow]) 
        {
            slow++;
            // 维护 nums[0..slow] 无重复
            nums[slow] = nums[fast];
        }
        fast++;
    }
    // 长度为索引 + 1
    return slow + 1;
}

四、代码:链表

给你一个有序链表,如何去重呢?其实和数组是一模一样的,唯一的区别是把数组赋值操作变成操作指针而已:

ListNode deleteDuplicates(ListNode head) 
{
    if (head == null) return null;
    ListNode slow = head, fast = head.next;
    
    while (fast != null) 
    {
        if (fast.val != slow.val) 
        {
            // nums[slow] = nums[fast];
            slow.next = fast;
            // slow++;
            slow = slow.next;
        }
        // fast++
        fast = fast.next;
    }
    // 断开与后面重复元素的连接
    slow.next = null;
    return head;
}
0

评论区