首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

單向鏈表找倒數第 N 節點:雙指針法與長度法完整解析

     編輯:Java 程式設計入門

問題描述

給定單向鏈表頭節點 head 與整數 n,找出倒數第 n 個節點 (即正數第 size - n + 1 個)。要求單次遍歷、O(1) 空間。

方法一:雙指針 (快慢指針) —— 推薦

核心思想: 讓快指針 q 先走 n 步,再與慢指針 p 同步前進。當 q 抵達尾部,p 恰好位於倒數第 n 節點。

C/C++ 實作

struct Node { int val; Node* next; };

Node* findNthToLast(Node* head, int n) {
    if (!head || n < 1) return nullptr;

    Node *p = head, *q = head;
    // q 先走 n 步
    for (int i = 0; i < n; ++i) {
        if (!q) return nullptr; // 鏈表長度 < n
        q = q->next;
    }
    // 同步前進
    while (q) {
        p = p->next;
        q = q->next;
    }
    return p;
}

Java 實作

class ListNode { int val; ListNode next; }

public ListNode nthToLast(ListNode head, int n) {
    if (head == null || n < 1) return null;

    ListNode p1 = head, p2 = head;
    // p2 先走 n-1 步 (或 n 步,視邊界定義)
    for (int i = 0; i < n - 1; ++i) {
        if (p2 == null) return null;
        p2 = p2.next;
    }
    // 同步直到 p2 到達最後一個節點
    while (p2.next != null) {
        p1 = p1.next;
        p2 = p2.next;
    }
    return p1;
}

方法二:先算長度再定位

思想: 先遍歷一次得長度 len,倒數第 n 即正數第 len - n + 1 個,再走一次。

  • 優點:邏輯直觀、易驗證邊界。
  • 缺點:需兩次遍歷 (仍為 O(N) 時間),不如雙指針優雅。
// 概略碼
int len = 0;
for (Node* cur = head; cur; cur = cur->next) len++;
if (n > len) return null;
int target = len - n + 1;
Node* cur = head;
for (int i = 1; i < target; ++i) cur = cur->next;
return cur;

邊界條件檢查清單

輸入預期回傳處理邏輯
head = nullnull首行判斷
n <= 0null首行判斷
n > 鏈表長度null快指針走步時提前遇到 null
n == 鏈表長度頭節點快指針走完即為 null,慢指針未動
n == 1尾節點快指針先走 1 步,同步至尾

複雜度分析

  • 時間: O(N) — 單次遍歷 (雙指針) 或雙次遍歷 (長度法)
  • 空間: O(1) — 僅使用常數額外指標

延伸應用

  • 刪除倒數第 N 節點 (LeetCode 19): 需定位前驅節點,可引入 dummy 頭節點簡化邊界。
  • 找中點: 快指針每次走 2 步,慢指針走 1 步 (快慢指針變體)。
  • 環檢測: 快慢指針相遇判斷 (Floyd 算法)。

總結

**雙指針法** 是解決「倒數第 K 個」問題的標準解法,單次遍歷、無額外空間、代碼簡潔。面試與實務中請熟練掌握其邊界處理 (n 過大、空鏈表、刪除節點需前驅等)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved