劍指offer面試題15 連結串列中倒數第K個結點

頭像是我偶像發表於2017-07-03

一、題目

輸入一個連結串列,輸出該連結串列中倒數第K個結點。為符合大多數人的習慣,本題從1開始計數,即連結串列的尾結點是倒數第1個結點。例如一個連結串列有6個結點,從頭結點開始它們的值依次是1,2,3,4,5,6.則這個連結串列的倒數第3個結點為4.

二、思考與分析

因為本題中的連結串列是單向連結串列,單向連結串列的結點只有從前向後的指標而沒有從後往前的指標,因此不可能從尾結點向前回溯K步。

2.1 方法一

需要遍歷兩次連結串列,第一次統計出連結串列中結點的個數,第二次就能找到倒數第K個結點,即從頭結點開始的第(n-k+1)的結點。

2.2 方法二

只需要遍歷一次連結串列,利用步長為(K-1的)尺子。

為了實現只遍歷連結串列一次就能找到倒數第K個結點,可以定義兩個指標。第一個指標從連結串列的頭指標開始遍歷向前走K-1步,第二個指標保持不動,這樣就形成了一個步長為(K-1)的尺子。從第K步開始,第二個指標也開始從連結串列的頭指標開始遍歷。直到第一個指標直到尾結點時,第二個指標正好是倒數第K個結點。

在有6個結點的連結串列上找倒數第3個結點的過程
在有6個結點的連結串列上找倒數第3個結點的過程

  1. 第一個指標在連結串列上走2(K-1)步,第二個指標保持不動;
  2. 從第3步開始,第二個指標和第一個指標同步向前移動,直到第一個指標到達尾結點。

2.3 程式碼實現

注意程式碼的魯棒性:
* 輸入連結串列為空時,即頭結點為空時,程式是否有處理?
* 輸入連結串列的長度小於K時,由於for迴圈會在連結串列上向前走K-1步,可能會因為空指標造成程式崩潰,對於這種情況程式是否有處理?
* 輸入的引數K為0是,那麼for迴圈在連結串列上向前走K-1步,即-1步,K是一個無符號整數,-1即為0XFFFFFFFF,因此for迴圈的次數會遠遠超出我們的預計,會造成程式崩潰,這種情況程式是否有處理?

 public ListNode FindKthToTail(ListNode head,int k) {
        if (head == null || k == 0) {
            return null;
        }
        ListNode n1 = head;
        ListNode n2 = head;
        for (int i = 0; i < (k-1); i++) {
            if (n1.next != null) {
                n1 = n1.next;
            } else {
                return null;
            }
        }
        while (n1.next != null) {
            n1 = n1.next;
            n2 = n2.next;
        }
        return n2;
   }

相關文章