如何刪除鏈表中值重復的節點


前言

  最近在刷《劍指offer》的題,其中有一道題目叫做刪除鏈表中重復的節點,我想了半天沒想到比較好的解決辦法,於是看了看大佬的解析(菜哭了)。不看不知道,一看嚇一跳,這尼瑪寫的也太妙了,忍不住寫篇博客記錄一下這個解題思路和代碼。


題目描述

  在一個排好序的鏈表中,存在重復的結點,請刪除該鏈表中重復的結點,重復的結點不保留,返回鏈表頭指針。 例如,鏈表1->2->3->3->4->4->5 處理后為 1->2->5


解題思路

  這道題我們分兩種情況來考慮:

  1. 首先第一種情況:頭節點的值存在重復;比如1->1->1->2->3->3->4,前面這個鏈表的頭節點重復了3次,所以這時候,我們應該舍棄前3個重復的節點1,將2作為新的頭節點,再繼續向后判斷;
  2. 第二種情況就是頭節點並不與它的下一個節點重復;比如上面的這個鏈表,我們去除了前面的3個1之后,剩下2->3->3->4,這時候,頭節點不與后面的節點重復了,那我們保留頭節點,並繼續向后判斷,發現后面后面的兩個3發生了重復,於是,我們去除這個兩個節點,並讓原來頭節點的next指向去除重復后的下一個位置,也就變成了2->4;若4后面還有其他重復,則我們去除重復后,讓4指向剩下的部分;

代碼實現

  其實上面的思路並不是很難想到,關鍵是代碼如何實現呢?下面這個代碼就是大佬對於上面這個思路的實現:

public ListNode deleteDuplication(ListNode pHead) {
    // 若頭節點為空,或者鏈表只有一個節點,則必沒有重復,值將返回
    if(pHead == null || pHead.next == null) {
        return pHead;
    }

    // 保存頭節點的下一個節點,上面已經判斷了pHead.next不是空
    ListNode next = pHead.next;
    // 若頭節點的值與下一個節點的值相同
    if(pHead.val == next.val) {
        do{
            // 則繼續向前找出與頭節點重復的節點
            // 直到找到第一個與頭節點不同的節點后,退出循環
            next = next.next;
        }while(next != null && next.val == pHead.val);

        // 舍棄前面的所有重復節點,將當前第一個與頭節點不同的節點作為頭節點,遞歸調用原方法,並直接返回
        return deleteDuplication(next);
    }else {
        // 若頭節點與它的下一個節點值不同,則將頭節點的下一個節點作為頭節點,遞歸調用方法
        // 並將返回值賦給頭節點的next屬性
        pHead.next = deleteDuplication(next);
        return pHead;
    }
}
// 以下是節點ListNode
class ListNode {
	int val;
	ListNode next = null;

	ListNode(int val) {
		this.val = val;
	}
}

  上面的代碼我加了點注釋,看得難受可以復制到編輯器中,刪掉注釋再看。

  上面這段代碼,給我的感覺就是把遞歸用的出神入化(可能是我太菜了)。除去注釋,短短幾行代碼,就將上面的思路完全實現,下面我來解讀一下:

  上面的代碼首先做了特判,若傳入的頭節點是空,或者沒有后續節點,那就不用去重,直接返回。這之后,先將頭節點的下一個節點保存。

  我們先判斷當前是否滿足前面說的第一種情況:頭節點發生了重復,若發生了這種情況,就一直向后找,直到找到第一個不與頭節點重復的節點,然后我們舍棄前面的節點,把這個節點當作頭節點,遞歸調用方法,並直接將返回值返回,這相當於是把后面剩下的部分當作一條新的鏈表,而前面重復的就直接舍棄了;

  若當前鏈表是我們之前說的第二種情況:頭節點不重復,則我們將頭節點的下一個節點作為參數,遞歸調用原方法,將除去頭節點后的子鏈表看作是一個新鏈表,而方法返回值就是這個子鏈表去重后的鏈表,我們將其與原來頭節點關聯,就完整地去重了。

  上面代碼最精妙的地方就是遞歸,將原鏈表中除去頭節點的剩余部分,當作一個新鏈表進行處理,短短幾行代碼,就實現了去重。


免責聲明!

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



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