數據結構書籍尚未看完,暫時只看了一部分的《大話數據結構》,因此對鏈表只是有點了解。面試
而後在LeetCode每日打卡中遇到這道題————https://leetcode-cn.com/problems/middle-of-the-linked-list(876 鏈表的中間結點)數組
相信這道題對於大佬甚至小白來講都是很簡單的一道題,可是我不會啊,因此就去看了一下題解,就發現了所謂的快慢指針,因此在此作一下筆記,但願各位不要嘲笑。數據結構
快慢指針就是定義兩根指針,其位置一快一慢,以此來製造出本身想要的差值。這個差值可讓咱們找到鏈表上相應的節點以及一系列操做函數
對於單鏈表,每一個結點只有一個存儲下一結點的 next 指針。當咱們在查找某個結點的時候,沒法和數組同樣經過下標快速定位到待查詢的結點,只能從頭結點開始,經過每一個結點的 next 指針,一個個結點的匹配查找。spa
這就表明了單鏈表循環的一個特色,它在遍歷上沒法後悔,遍歷走過了,就是過了,沒法回頭。除非再用一個數據結構去記錄已經遍歷的結點,那就再也不是一個單純的單鏈表了。因此當咱們遇到一個指針遍歷鏈表不能解決問題的時候,能夠嘗試用兩個指針來遍歷鏈表。這就引起出一種解決方案,就是快慢指針,一個指針沒法完成任務,那就再引入一個指針。它經過兩個指針 fast 和 slow 指針,讓兩個指針保持必定的間隔規律,達到咱們查找的目的。指針
1. 找出鏈表的中間節點
2. 判斷鏈表是否存在環
3. 刪除鏈表的倒數第n的節點
4. 將有序鏈表轉換爲二叉搜索樹code
給定一個帶有頭結點 head 的非空單鏈表,返回鏈表的中間結點。對象
若是有兩個中間結點,則返回第二個中間結點。blog
示例 1:排序
輸入:[1,2,3,4,5]
輸出:此列表中的結點 3 (序列化形式:[3,4,5])
返回的結點值爲 3 。 (測評系統對該結點序列化表述是 [3,4,5])。
注意,咱們返回了一個 ListNode 類型的對象 ans,這樣:
ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, 以及 ans.next.next.next = NULL.示例 2:
輸入:[1,2,3,4,5,6]
輸出:此列表中的結點 4 (序列化形式:[4,5,6])
因爲該列表有兩個中間結點,值分別爲 3 和 4,咱們返回第二個結點。
用快慢兩個指針 slow 與 fast 一塊兒遍歷鏈表。根據兩個指針之間的間隔,來達到咱們的目的,因此使slow 一次走一步,fast 一次走兩步。那麼當 fast 到達鏈表的末尾時,slow 必然位於中間。
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */
//鏈表的中間結點
class Solution {//用兩個指針 slow 與 fast 一塊兒遍歷鏈表。slow 一次走一步,fast 一次走兩步。那麼當 fast 到達鏈表的末尾時,slow 必然位於中間。
public ListNode middleNode(ListNode head) {//快慢指針
ListNode fast = head;
ListNode slow = head;
while(fast != null && fast.next != null){//由於後面是fast = fast.next.next,因此若fast.next爲空,則會產生異常;
fast = fast.next.next;
slow = slow.next;
//若鏈表爲單數,則最終fast.next=null,結束循環,slow爲中間結點
//若鏈表爲雙數,則最終fast=null,結束循環,slow=(len+1)/2的中間結點;
}
return slow;
}
}
此題出自LeetCode——https://leetcode-cn.com/problems/lian-biao-zhong-dao-shu-di-kge-jie-dian-lcof/(面試題2二、鏈表中倒數第K個結點)
輸入一個鏈表,輸出該鏈表中倒數第k個節點。爲了符合大多數人的習慣,本題從1開始計數,即鏈表的尾節點是倒數第1個節點。
例如,一個鏈表有6個節點,從頭節點開始,它們的值依次是一、二、三、四、五、6。這個鏈表的倒數第3個節點是值爲4的節點。
示例:
給定一個鏈表: 1->2->3->4->5, 和 k = 2.
返回鏈表 4->5.
讓快指針先走k步,而後兩個指針同時走到頭時,慢指針就是鏈表倒數第k個結點;
注意點:
這題中咱們須要注意,若是輸入的k大於鏈表的結點數,須要怎樣進行判斷,若是k小於等於0,還有就是須要注意空指針的問題。
給定一個鏈表,判斷鏈表中是否有環。
若是鏈表中有某個節點,能夠經過連續跟蹤 next 指針再次到達,則鏈表中存在環。 爲了表示給定鏈表中的環,咱們使用整數 pos 來表示鏈表尾鏈接到鏈表中的位置(索引從 0 開始)。 若是 pos 是 -1,則在該鏈表中沒有環。注意:pos 不做爲參數進行傳遞,僅僅是爲了標識鏈表的實際狀況。
若是鏈表中存在環,則返回 true 。 不然,返回 false 。
出自:https://leetcode-cn.com/problems/linked-list-cycle
題目描述
示例 :
輸入:head = [3,2,0,-4], pos = 1輸出:true解釋:鏈表中有一個環,其尾部鏈接到第二個節點。
public class Solution { public boolean hasCycle(ListNode head) { if(head == null || head.next == null){ return false; } ListNode fast = head.next;//fast和slow設置不同的值,是由於下面的循環,如果值同樣,循環在初始狀況下就終止了。
ListNode slow = head; while(fast != slow){ if(fast == null || fast.next == null){ return false; } fast = fast.next.next; slow = slow.next; } return true; } }
此爲LeetCode題——https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/(2六、刪除排序數組中的重複項)
給定一個排序數組,你須要在 原地 刪除重複出現的元素,使得每一個元素只出現一次,返回移除後數組的新長度。
不要使用額外的數組空間,你必須在 原地 修改輸入數組 並在使用 O(1) 額外空間的條件下完成。
示例:
給定數組 nums = [1,1,2],
函數應該返回新的長度 2, 而且原數組 nums 的前兩個元素被修改成 1, 2。
你不須要考慮數組中超出新長度後面的元素。
能夠放置兩個指針slow和fost,由於是有序數組,因此當fost指針指向的值不等於slow指向的值時,那麼就能夠將此時fost指向的值添加到此時slow指針的位置,而且將slow加一;