1. 程式人生 > >演算法---輸出單向連結串列中倒數第K個節點

演算法---輸出單向連結串列中倒數第K個節點

    輸出單向連結串列中倒數第K個節點,比如我們現在有int型別的1,2,3,4,5,6,7,8組成的一個單向連結串列,求倒數第三個元素。如圖所示:


    我們正常的思路就是從後往前推倒數第K個元素,這裡有這樣幾個問題。首先是單向連結串列的限制,連結串列節點只有next指標指向下一個元素,所以我們只能從前往後推;其次我們需要知道最後一個元素後才能從後往前倒推,這裡就只能通過next指標由前往後遍歷,這是第一次迴圈,然後從後往前推又要開始遍歷,這是第二次迴圈;另外如果從後往前推這也是個問題;或者說第一次迴圈時知道了單項鍊表長度,然後通過倒數第K個,我們能推匯出是正數第幾個,這樣再從前往後迴圈一次就能獲取這個節點,但是這樣還是迴圈了兩次。

    這裡我們只介紹目前瞭解到的最優的解決方案,其他方法就不一一介紹了。

    我們通過兩個指標和一次迴圈就能得到想要的節點,步驟如下:

  1. 最後一個節點與倒數第K個節點之間的距離為K-1。指定兩個指標P1和pP2,P1從頭結點開始先移動K-1步,停下來。
  2. P1停下來後,P2指向第一個節點,注意此時P1與P2之間的距離正好是最後一個節點和倒數第K個節點間的距離。
  3. P1和P2同時向後移動,當P1移動到最後一個節點的位置時停下來,此時P2的位置就正好是倒數第K個元素的位置了,那麼P2處的節點就是我們想要的倒數第K個節點。

    我們可以按上圖中的連結串列來試算下。有 1,2,3,4,5,6,7,8這樣順序的一個單項鍊表,求倒數第3個節點。倒數第三個節點與最後一個節點的距離是3-1=2。先定義P1指標,從頭節點移動2步,到達節點3的位置停下來,這時定義P2節點指向頭節點,也就是節點1,然後P1和P2節點同時向後移動,當P1節點移動到最後一個節點8時,此時P1移動到了節點6處,而節點6就是倒數第3個節點,ok,節點6就是我們要的節點。

    程式碼實現:

public class SingleLinkedNode {

    //節點上儲存的資料
    private Object data;

    //該節點的下一個節點
    private SingleLinkedNode next;

    public SingleLinkedNode(Object data){
        this.data = data;
    }
   
    ......
}
public static SingleLinkedNode getReverseKPathNode(SingleLinkedNode head , int  k){
        //定義兩個指標P1和P2,這裡直接用節點表示
        SingleLinkedNode P1 = head;
        SingleLinkedNode P2 = head;
        //P1移動到K-1位置停下來
        for(int i=1;i<=k-1;i++){
            P1=P1.getNext();
        }

        //P1和P2同時向後移動,直到P1節點移動到最後一個節點
        while(P1.getNext()!=null){
            P1 = P1.getNext();
            P2 = P2.getNext();
        }
        //此時P2節點就是倒數第K個節點
        return P2;
}

    測試:

public static void main(String[] args){
        SingleLinkedNode node1 = new SingleLinkedNode(1);
        SingleLinkedNode node2 = new SingleLinkedNode(2);
        SingleLinkedNode node3 = new SingleLinkedNode(3);
        SingleLinkedNode node4 = new SingleLinkedNode(4);
        SingleLinkedNode node5 = new SingleLinkedNode(5);
        SingleLinkedNode node6 = new SingleLinkedNode(6);
        SingleLinkedNode node7 = new SingleLinkedNode(7);
        SingleLinkedNode node8 = new SingleLinkedNode(8);
        node1.setNext(node2);
        node2.setNext(node3);
        node3.setNext(node4);
        node4.setNext(node5);
        node5.setNext(node6);
        node6.setNext(node7);
        node7.setNext(node8);
        System.out.println(getReverseKPathNode(node1,3).getData());
}

    執行結果為:6,。正確