劍指Offer題目15:鏈表中倒數第k個結點(Java)

面試題15:輸入一個鏈表,輸出該鏈表中倒數第k個結點。爲了符合大多數人的習慣,本題從1開始計數,即鏈表的尾結點是倒數第1個結點。例如一個鏈表有6個結點,從頭結點開始它們的值依次是一、二、三、四、五、6。這個鏈表的倒數第3個結點是值爲4的結點。面試

Basic

頭指針和中間指針向前遍歷法(自創詞彙方便記憶)

設置頭指針和中間指針,保持相同間隔,朝着同一個方向向前遍歷鏈表。bash

思路分析

須要注意 k <= 0 的場景和k大於鏈表長度的場景。oop

代碼實現

public class Solution {
    public ListNode FindKthToTail(ListNode head,int k) {
        if(k <= 0 || head == null) {
            return null;
        }
        ListNode front = head;
        ListNode back = head;
        for(int i=0; i< k-1; i++) {
            //這裏須要經過在紙上畫出臨界點的場景,好比只有5個節點,求倒數第5個節點和倒數第6個節點的場景
            //倒數第5個:k-1 = 4, i 從0~3,總共循環4次,最終遍歷到頭結點的後序4個節點,即尾節點
            //倒數第6個:k-1 = 5, i 從0~4,總共循環5次,最終遍歷到出界,若是出現back.next == null,說明出界了
            if(back.next == null){
                return null;
            }
            back = back.next;
        }
        while(back.next != null){
            front = front.next;
            back = back.next;
        }
        return front;
        
    }
}
複製代碼

擴展

題目1:求鏈表的中間節點

若是鏈表中的總數爲奇數,返回中間節點;若是爲偶數,返回中間兩個節點的任意一個。ui

思路分析

定義兩個指針,同時從鏈表頭結點出發,一個指針一次走一步,另外一個指針一次走兩步。spa

當走得快的指針走到鏈表末尾時,走得慢的指針正好在鏈表中間。3d

能夠在紙上模擬。指針

代碼實現

public static Node findMiddleNode(Node head) {
    if (head == null) {
        return null;
    }
    if (head.next == null) {
        return head;
    }
    Node slow = head;
    Node fast = head;
    //一、當鏈表有偶數個節點時,能夠遍歷到倒數第 2 個節點,因爲能夠返回中間兩個節點的任意一個,
    // 此時慢指針恰好就是其中兩個中間節點的前一個節點,此時定位結束。
    //二、當鏈表有奇數個節點時,能夠遍歷到最後一個節點,此時慢指針恰好到正中間的節點,定位結束
    while (fast.next != null && fast.next.next != null) { 
        slow = slow.next;
        fast = fast.next.next;
    }
    return  slow;
}
複製代碼

題目2:判斷一個單向鏈表是否造成了環結構。

思路分析

定義兩個指針,同時從鏈表頭結點出發,一個指針一次走一步,另外一個指針一次走兩步。code

若是走得快的指針追上了走得慢的指針,那麼鏈表就存在環形結。cdn

若是走得快的指針走到了鏈表末尾,即 next 爲 null,則代表鏈表不存在環形結構。blog

能夠在紙上模擬。

代碼實現

public static boolean isLoop(Node head) {
    if (head == null || head.next == null) {
        return false;
    }
    Node oneStepNode = head;
    Node twoStepNode = head;
    while (twoStepNode.next != null && twoStepNode.next.next != null) {
        oneStepNode = oneStepNode.next;
        twoStepNode = twoStepNode.next.next;
        //注意避免死循環
        if (oneStepNode == twoStepNode) {
            return true;
        }
    }
    return false;
}
複製代碼

相關文章
相關標籤/搜索