1. 程式人生 > >刪除連結串列中重複的結點——牛客劍指offer

刪除連結串列中重複的結點——牛客劍指offer

題目描述:

在一個排序的連結串列中,存在重複的結點,請刪除該連結串列中重複的結點,重複的結點不保留,返回連結串列頭指標。 例如,連結串列1->2->3->3->4->4->5 處理後為 1->2->5

解題思路:

首先初始化一個起始指標preNode指向頭結點、工作指標walkNode指向連結串列的第一個元素,即preNode.next=walkNode。

迭代開始:

while(walkNode!=null){

  如果當前工作結點的資料域walkNode.val與下一個結點的資料域walkNode.next.val相同(出現重複結點):

    preNode不移動;(指向重複結點段的前一個結點)

    walkNode移動:walkNode=walkNode.next;(此時preNode.next!=walkNode)

  否則,

    如果preNode.next==walkNode(說明未出現重複節點):

      preNode移動,walkNode移動:preNode=walkNode;walkNode=walkNode.next;

         否則,說明有重複結點,此時preNode指向重複結點段的前一個結點,walkNode指向重複結點段的最後一個重複結點

      使preNode直接指向重複結點段的下一個結點:preNode.next=walkNode.next;

      walkNode移動:walkNode=walkNode.next;

}

注意:因為可能會刪除頭結點,例如{1,1,1,2},刪除了頭結點1和第一個結點1,結果應為{2}。但是如果直接將函式傳進來的pHead作為頭結點,即初始化preNode=pHead,那麼頭節點永遠不可能被刪除,得到的結果只能為{1,2}。

因此這裡添加了一個新的頭節點newhead,將pHead當一般結點處理,初始化preNode=newhead這樣就可以避免出現上面的錯誤。

舉例:

1->2->3->3->4->4 (加入新頭結點newhead:newhead.val=0,;ewhead.next=pHead) 0->1->2->3->3->4->4

初始化:

preNode指向新的頭結點,walkNode指向第一個結點

preNode=newNode

walkNode=newhead.next

第1次迭代:

walkNode1與其下一個結點2不相同,而且preNode0和walkNode1相鄰,說明之前也沒有出現過重複結點,所以把兩個指標都前移

walkNode.next.val!=walkNode.val&&pre.next==walkNode:pre=walkNode;walkNode=walkNode.next; 

第2次迭代:

同第一次迭代

walkNode.next.val!=walkNode.val&&pre.next==walkNode:pre=walkNode;walkNode=walkNode.next; 

第3次迭代:

walkNode3與下一個結點3重複,那麼此時preNode不移動,只移動walkNode

walkNode.next.val==walkNode.val:walkNode=walkNode.next

第4次迭代:

walkNode3與其下一個結點4不相同,但是此時preNode和walkNode不相鄰,說明preNode和walkNode中間出現了重複結點,所以把preNode直接指向walkNode的下一個結點,拋棄中間重複節點

walkNode.next.val!=walkNode.val&&pre.next!=walkNode:pre.next=walkNode.next;walkNode=walkNode.next; 

第5次迭代:

walkNode4與下一個結點4重複,那麼此時preNode不移動,只移動walkNode

walkNode.next.val==walkNode.val:walkNode=walkNode.next

第6次迭代:

walkNode.next==null&&pre.next!=walkNode:pre.next=walkNode.next;return newNode.next;

程式碼實現

package struct;
public class deleteList {
//public class ListNode {
//    int val;
//    ListNode next = null;
//    ListNode(int val) {
//        this.val = val;
//   }
//}
    public ListNode printListFromTailToHead(ListNode pHead) {
        ListNode newhead=new ListNode(0);//解決刪除頭結點的可能,例如{1,1,1,1,2}
        newhead.next=pHead;
        ListNode pre=newhead;
        ListNode walkNode=newhead.next;
        while(walkNode!=null){
            if(walkNode.next!=null){
                if(walkNode.next.val!=walkNode.val){
                    if(pre.next!=walkNode)
                    {
                        pre.next=walkNode.next;    
                    }
                    else
                    {
                        pre=walkNode;
                    }
                }
            }
            else{                      //如果walkNode指向最後一個結點
                if(pre.next!=walkNode)
                {
                    pre.next=walkNode.next;    
                }
                else
                {
                    pre=walkNode;
                }
            }
            walkNode=walkNode.next;    
        }
        return newhead.next;    
    }
}