Remove duplicate 问题

本文主要探讨了LeetCode上的四道关于从链表和数组中删除重复元素的问题,这些问题都可以通过双指针技巧来解决。在处理过程中,需特别注意终止条件和移动指针的时机,避免空指针异常。当prev节点后面不是重复节点时,双指针同时后移;若为重复节点,则将second指针移到第一个不同值的节点,删除中间的重复节点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

leetcode上有四道题,主要是remove from linked list和array

都是two pointer解决,要注意终止条件,还有移动指针时条件

3 Remove from sorted list
Given 1->1->2->3->3, return 1->2->3
注意while终止条件都是第二个指针到达末尾(null)
(1)第二个指针向后扫描,扫描的同时删除,优势是只需要一重循环!
public ListNode delete(ListNode hea){
        if(head == null) return null;
        
        ListNode first = head;
        ListNode second = head.next;
        //move second pointer forward and remove duplicate 
        while(second != null){
                //remove if duplicate
                if(second.val == first.val){
                        first.next = second.next;
                        
                }else{
                        first = second;
                }
                second = second.next;
        }
        return head;
}

(2) 第二个指针向后查找第一个不同value的元素,删除first和second之间所有duplicate

这里注意 1- > 1 -> null

第二个指针赋值要在while移动前,因为有可能上一次已经达到tail,first = second之后,first为null,如果second = first.next 就会空指针异常。

public ListNode deleteDuplicates(ListNode head) {
        if(head == null) return null;
	
    	ListNode first = head;
	    ListNode second = first.next;
	    //move second pointer forward and find the first node with different value
	    while(second != null){
	         second = first.next;
		    while(second != null && second.val == first.val)second = second.next;
		    first.next = second;
		    first = first.next;
		    //second = first.next; // first may be null
		   
	    }
	    return head;
    }

4 Remove duplicates from sorted list II

Given 1->2->3->3->4->4->5, return 1->2->5
Given 1->1->1->2->3, return 2->3.

不同之处第一个指针需要在first之前,这样引入dummy node。

(1) prev后不是重复点,直接后移两个指针

prev后为重复node,需要删除,移动second指针到第一个不同于值得node,删除中间所有duplicate node

	public ListNode deleteDuplicates(ListNode head) {
        if(head == null || head.next == null) return head;
        
        //two pointer, but need to keep prev, use dummy node
        ListNode dummy = new ListNode(-1);
        dummy.next = head;
        ListNode prev = dummy;  
        ListNode second = prev.next.next;
      
        while(second != null){
            second = prev.next.next;
           if(second != null && second.val == prev.next.val){
               //move forward
               while(second != null && second.val == prev.next.val) second = second.next;
               prev.next = second;
           }else{
               prev = prev.next;
           }
        }
        return dummy.next; 
	}


(2) 边扫描边删除

public ListNode delete(ListNode head) {
        if(head == null || head.next == null){
            return head;
        }
        ListNode dummy = new ListNode(-1);
        dummy.next = head;
	ListNode prev = dummy;
		
        while(second != null){
	    second = prev.next.next;
            if(second != null && second.val == prev.next.val){
			int value = prev.next.val; // store in temporary value
			//move forward and delete
			while(second != null && second.val == value){
				second = second.next;
				prev.next = second; // delete
			}
				
		}else{
			//no duplicate, can move prev pointer
			prev = prev.next;
		}
        }
        
        return dummy.next;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值