【劍指Offer學習】【面試題15 :連結串列中倒數第k個結點】
阿新 • • 發佈:2019-02-07
題目:輸入一個連結串列,輸出該連結串列中倒數第k 個結點.為了符合大多數人的習慣,本題從1 開始計數,即連結串列的尾結點是倒數第1 個結點.例如一個連結串列有6 個結點,從頭結點開始它們的值依次是1 、2、3、4、5 、6。這個個連結串列的倒數第3 個結點是值為4 的結點.
連結串列結點定義如下:
public static class ListNode {
int value;
ListNode next;
}
解題思路:
為了實現只遍歷連結串列一次就能找到倒數第k 個結點,我們可以定義兩
個指標。第一個指標從連結串列的頭指標開始遍歷向前走k-1步,第二個指標保持不動;從第k 步開始,第二個指標也開始從連結串列的頭指標開始遍歷。由於兩個指標的距離保持在k-1 , 當第一個(走在前面的)指標到達連結串列的尾結點時,第二個指標(走在後面的)指標正好是倒數第k 個結點。
程式碼實現:
public class Test15 {
public static class ListNode {
int value;
ListNode next;
}
/**
* 輸入一個鍵表,輸出該連結串列中倒數第k 個結點.為了符合大多數人的習慣,
* 本題從1開始計數,即連結串列的尾結點是倒數第1個結點.例如一個連結串列有6個結點,
* 從頭結點開始它們的值依次是1、2、3、4、5 6。這個連結串列的倒數第3個結點是值為4的結點.
*
* @param head 連結串列的頭結點
* @param k 倒數第k個結點
* @return 倒數第k個結點
*/
public static ListNode findKthToTail(ListNode head, int k) {
// 輸入的連結串列不能為空,並且k大於0
if (k < 1 || head == null) {
return null;
}
// 指向頭結點
ListNode pointer = head;
// 倒數第k個結點與倒數第一個結點相隔k-1個位置
// pointer先走k-1個位置
for (int i = 1; i < k; i++) {
// 說明還有結點
if (pointer.next != null) {
pointer = pointer.next;
}
// 已經沒有節點了,但是i還沒有到達k-1說明k太大,連結串列中沒有那麼多的元素
else {
// 返回結果
return null;
}
}
// pointer還沒有走到連結串列的末尾,那麼pointer和head一起走,
// 當pointer走到最後一個結點即,pointer.next=null時,head就是倒數第k個結點
while (pointer.next != null) {
head = head.next;
pointer = pointer.next;
}
// 返回結果
return head;
}
public static void main(String[] args) {
ListNode head = new ListNode();
head.value = 1;
head.next = new ListNode();
head.next.value = 2;
head.next.next = new ListNode();
head.next.next.value = 3;
head.next.next.next = new ListNode();
head.next.next.next.value = 4;
head.next.next.next.next = new ListNode();
head.next.next.next.next.value = 5;
head.next.next.next.next.next = new ListNode();
head.next.next.next.next.next.value = 6;
head.next.next.next.next.next.next = new ListNode();
head.next.next.next.next.next.next.value = 7;
head.next.next.next.next.next.next.next = new ListNode();
head.next.next.next.next.next.next.next.value = 8;
head.next.next.next.next.next.next.next.next = new ListNode();
head.next.next.next.next.next.next.next.next.value = 9;
System.out.println(findKthToTail(head, 1).value); // 倒數第一個
System.out.println(findKthToTail(head, 5).value); // 中間的一個
System.out.println(findKthToTail(head, 9).value); // 倒數最後一個就是順數第一個
System.out.println(findKthToTail(head, 10));
}
}
執行結果: