面試題15:輸入一個鏈表,輸出該鏈表中倒數第k個結點。爲了符合大多數人的習慣,本題從1開始計數,即鏈表的尾結點是倒數第1個結點。例如一個鏈表有6個結點,從頭結點開始它們的值依次是一、二、三、四、五、6。這個鏈表的倒數第3個結點是值爲4的結點。面試
設置頭指針和中間指針,保持相同間隔,朝着同一個方向向前遍歷鏈表。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;
}
}
複製代碼
若是鏈表中的總數爲奇數,返回中間節點;若是爲偶數,返回中間兩個節點的任意一個。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;
}
複製代碼
定義兩個指針,同時從鏈表頭結點出發,一個指針一次走一步,另外一個指針一次走兩步。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;
}
複製代碼