【Java】 劍指offer(18) 刪除鏈表中重復的結點


本文參考自《劍指offer》一書,代碼采用Java語言。

更多:《劍指Offer》Java實現合集  

題目

  在一個排序的鏈表中,如何刪除重復的結點?例如,在圖3.4(a)中重復結點被刪除之后,鏈表如圖3.4(b)所示。

思路

  設置一個preNode,用於記錄當前結點的前一個結點,再設置一個布爾變量needDelete,如果當前結點和后一結點的值相同(記該值為dupVal),needDelete賦值為真。

  當needDelete為真時,通過循環往后找到第一個不為dupVal的結點,把該結點設置為當前結點,並賦值給preNode.next,即相當於完成了刪除操作;而當needDelete為假時,把當前結點和preNode往后移一位即可。

測試算例

  1.功能測試(重復結點位於鏈表頭部、中部、尾部,無重復結點)

  2.特殊測試(null,所有結點均重復)

完整Java代碼

    public ListNode deleteDuplication(ListNode pHead){
        ListNode pre = null;
        ListNode cur = pHead;
        while(cur!=null){
            if(cur.next!=null && cur.next.val==cur.val){
                while(cur.next!=null && cur.next.val==cur.val)
                    cur=cur.next;
                cur=cur.next;
                if(pre==null)
                    pHead=cur;
                else
                    pre.next=cur;
            }else{
                pre=cur;
                cur=cur.next;
            }
        }
        return pHead;
    }
復習時寫的

 

(含測試代碼)

package _18;

/**
 * 
 * @Description 面試題18(二):刪除鏈表中重復的結點
 *
 * @author yongh
 * @date 2018年9月18日 下午6:30:53
 */

// 題目:在一個排序的鏈表中,如何刪除重復的結點?例如,在圖3.4(a)中重復
// 結點被刪除之后,鏈表如圖3.4(b)所示。

public class DeleteDuplicatedNode {
	class ListNode{
		   int val;
		    ListNode next = null;

		    ListNode(int val,ListNode next) {
		        this.val = val;
		        this.next=next;
		    }
	}
    public ListNode deleteDuplication(ListNode pHead){
        if(pHead==null||pHead.next==null) //空結點或者僅一個結點
            return pHead;
        ListNode preNode = null;
        ListNode curNode = pHead;
        
        while(curNode!=null){
            boolean needDelete=false;
            if(curNode.next!=null && curNode.val==curNode.next.val)
                needDelete=true;
            if(!needDelete){  //當前結點不重復
                preNode=curNode;
                curNode=curNode.next;
            }else{            //當前結點重復
                int dupValue=curNode.val;
                ListNode toBeDel = curNode;
                while(toBeDel!=null&&toBeDel.val==dupValue){
                    //這里刪除暫時不涉及前一結點操作,其實主要是找出后面第一個不重復結點
                    toBeDel = toBeDel.next;
                }
                if(preNode==null){  //說明刪除的結點為頭結點
                    pHead=toBeDel;
                }else{
                    preNode.next=toBeDel;
                }
                curNode=toBeDel;  //這個結點還是可能會出現重復的,所以不能=next
            }
        }
        return pHead;
    }
	
    
    //========測試代碼======
	void test(ListNode pHead) {
		System.out.println("-----------");
		System.out.print("The original list is: ");
		ListNode curr=pHead;
		if(curr!=null) {
			while(curr.next!=null) {
				System.out.print(curr.val+",");
				curr=curr.next;
			}
			System.out.println(curr.val);
		}else {
			System.out.println();
		}
		pHead=deleteDuplication(pHead);
		System.out.print("The result list is: ");
		curr=pHead;
		if(curr!=null) {
			while(curr.next!=null) {
				System.out.print(curr.val+",");
				curr=curr.next;
			}
			System.out.println(curr.val);
		}else {
			System.out.println();
		}
		System.out.println("-----------");
	}
    
	
	/**
	 * 重復結點位於鏈表頭部
	 */
	void test1() {
		ListNode p4=new ListNode(3, null);
		ListNode p3=new ListNode(2, p4);
		ListNode p2=new ListNode(1, p3);
		ListNode p1=new ListNode(1, p2);
		test(p1);
	}
	
	/**
	 * 重復結點位於鏈表尾部
	 */
	void test2() {
		ListNode p4=new ListNode(3, null);
		ListNode p3=new ListNode(3, p4);
		ListNode p2=new ListNode(2, p3);
		ListNode p1=new ListNode(1, p2);
		test(p1);
	}
	
	/**
	 * 重復結點位於鏈表中部
	 */
	void test3() {
		ListNode p4=new ListNode(3, null);
		ListNode p3=new ListNode(2, p4);
		ListNode p2=new ListNode(2, p3);
		ListNode p1=new ListNode(1, p2);
		test(p1);
	}
	
	/**
	 * 連續出現重復結點
	 */
	void test4() {
		ListNode p6=new ListNode(3, null);
		ListNode p5=new ListNode(3, p6);
		ListNode p4=new ListNode(2, p5);
		ListNode p3=new ListNode(2, p4);
		ListNode p2=new ListNode(1, p3);
		ListNode p1=new ListNode(1, p2);
		test(p1);
	}
	
	/**
	 * 多個重復結點
	 */
	void test5() {
		ListNode p6=new ListNode(3, null);
		ListNode p5=new ListNode(3, p6);
		ListNode p4=new ListNode(3, p5);
		ListNode p3=new ListNode(2, p4);
		ListNode p2=new ListNode(1, p3);
		ListNode p1=new ListNode(1, p2);
		test(p1);
	}
	
	/**
	 * 無重復結點
	 */
	void test6() {
		ListNode p6=new ListNode(6, null);
		ListNode p5=new ListNode(5, p6);
		ListNode p4=new ListNode(4, p5);
		ListNode p3=new ListNode(3, p4);
		ListNode p2=new ListNode(2, p3);
		ListNode p1=new ListNode(1, p2);
		test(p1);
	}
	
	/**
	 * 單個結點
	 */
	void test7() {
		ListNode p1=new ListNode(6, null);
		test(p1);
	}
    
	/**
	 * null
	 */
	void test8() {
		ListNode p1=null;
		test(p1);
	}
	
	public static void main(String[] args) {
		DeleteDuplicatedNode demo= new DeleteDuplicatedNode();
		demo.test1();
		demo.test2();
		demo.test3();
		demo.test4();
		demo.test5();
		demo.test6();
		demo.test7();
		demo.test8();
	}
    
	
	
}

  

-----------
The original list is: 1,1,2,3
The result list is: 2,3
-----------
-----------
The original list is: 1,2,3,3
The result list is: 1,2
-----------
-----------
The original list is: 1,2,2,3
The result list is: 1,3
-----------
-----------
The original list is: 1,1,2,2,3,3
The result list is: 
-----------
-----------
The original list is: 1,1,2,3,3,3
The result list is: 2
-----------
-----------
The original list is: 1,2,3,4,5,6
The result list is: 1,2,3,4,5,6
-----------
-----------
The original list is: 6
The result list is: 6
-----------
-----------
The original list is: 
The result list is: 
-----------
demo

 

收獲

  1.刪除多個結點時,只要把重復結點前一個結點的next指向重復結點的后一個結點;

  2.不要把重復結點一個一個刪除,先定義一個布爾變量確定當前結點是否重復,然后按上一句話的方法進行刪除即可。

 

更多:《劍指Offer》Java實現合集  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM