刷了LeetCode的鏈表專題,我發現了一個祕密!

{"type":"doc","content":[{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"刷了LeetCode的鏈表專題,我發現了一個祕密!"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"引言"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"鏈表"}]},{"type":"text","text":"是以節點(node)存儲的"},{"type":"codeinline","content":[{"type":"text","text":"鏈式存儲結構"}]},{"type":"text","text":",一個node包含一個data域(存放數據)和一個next域(存放下一個node的指針),鏈表的各個節點不一定是連續的,它可以分爲"},{"type":"codeinline","content":[{"type":"text","text":"帶頭結點"}]},{"type":"text","text":"和"},{"type":"codeinline","content":[{"type":"text","text":"不帶頭結點"}]},{"type":"text","text":"。頭結點僅包含next域。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/58/58ef4b3ce735eb6a8db02a6b51153f35.png","alt":"image-20201103222213252","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果不熟悉鏈表的同學,"},{"type":"link","attrs":{"href":"https://mp.weixin.qq.com/s/BOPP8JpDWNCqUfK8_SZtoA","title":""},"content":[{"type":"text","text":"建議先看看我的一篇文章"}]},{"type":"text","text":"。在這篇文章中,主要講解使用鏈表的小技巧,如何使用這些技巧來解題,深入解析了"},{"type":"codeinline","content":[{"type":"text","text":"LeetCode"}]},{"type":"text","text":"中具有"},{"type":"codeinline","content":[{"type":"text","text":"代表性"}]},{"type":"text","text":"的鏈表題目,相信我,看了這篇文章,你再也不用擔心關於鏈表的題目了。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"1、鏈表的幾個概念講解"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"事實上,鏈表的結構比較簡單,阻礙我們理解鏈表的常常是因爲鏈表的"},{"type":"codeinline","content":[{"type":"text","text":"指針"}]},{"type":"text","text":"、"},{"type":"codeinline","content":[{"type":"text","text":"邊界問題"}]},{"type":"text","text":"等,這有時會讓我們很煩躁,不要慌,我們下面一一對這下概念解析,相信你看了會有收穫。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"1.1鏈表中的的指針是什麼"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們學習C語言時,學過指針,它描述的是指向一個"},{"type":"codeinline","content":[{"type":"text","text":"內存地址"}]},{"type":"text","text":",在Java語言中,是不存在指針的,但是我們可以把它理解爲"},{"type":"codeinline","content":[{"type":"text","text":"引用"}]},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當我們將某個變量(對象)賦值給指針(引用),實際上就是將這個變量(對象)的地址賦值給指針(引用)。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"p—>next = q; //表示p節點的後繼指針存儲了q節點的內存地址。\np—>next = p—>next—>next; //表示p節點的後繼指針存儲了p節點的下下個節點的內存地址。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"1.1指針指向哪兒"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們寫鏈表代碼時,使用的指針的"},{"type":"codeinline","content":[{"type":"text","text":"指來指去"}]},{"type":"text","text":",很快就把我們搞糊塗了,在這種情況下很容易發生"},{"type":"codeinline","content":[{"type":"text","text":"指針丟失"}]},{"type":"text","text":"和"},{"type":"codeinline","content":[{"type":"text","text":"內存泄漏"}]},{"type":"text","text":"。我們先普及下這兩個概念:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"指針丟失"},{"type":"text","text":":自己定義的指針不知道指到哪裏了,沒有明確的指向。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"內存泄漏"},{"type":"text","text":":鏈表中的節點沒有確切的指針判斷,運行時會拋出空指針異常。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們以"},{"type":"codeinline","content":[{"type":"text","text":"插入節點"}]},{"type":"text","text":"和"},{"type":"codeinline","content":[{"type":"text","text":"刪除結點"}]},{"type":"text","text":"來分析指針丟失和內存泄漏的具體情況"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"插入節點"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在節點a和節點b之間插入節點x,b是a的下一節點,p指針指向節點a,"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"p—>next = x;\nx—>next = p—>next; "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這樣的代碼會造成指針丟失和內存泄漏,因爲這會導致x節點的後繼指針指向了自己本身。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"正確代碼應該爲:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"x—>next = p—>next;\np—>next = x;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/eb/ebe7935114019f64c193f798ba8b9e6f.png","alt":"image-20201103224355467","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"刪除節點"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"同樣的,在節點a和節點c之間刪除節點b,b是a的下一節點,p指針指向節點a,正確的代碼應該爲:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"p—>next = p—>next—>next;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/fd/fd06426aba7ed8b869ad72907626bf44.png","alt":"image-20201103234222288","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在刪除節點,考慮到刪除的節點可能是鏈表中的第一個節點,我們通常在鏈表頭部加入哨兵(頭結點),這樣可以使得刪除鏈表的代碼是一致的,不用再額外考慮是否是第一個節點的情況。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"在鏈表加入哨兵的代碼爲"},{"type":"text","text":":"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":" //定義一個哨兵作爲傳入鏈表的頭結點\n ListNode pre =new ListNode(0);\n pre.next=head;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/3e/3ee8a7d34cadfdb33ced390c2126b07e.png","alt":"image-20201103233816980","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"1.3判斷邊界的條件"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"處理鏈表問題時,要充分考慮鏈表的"},{"type":"codeinline","content":[{"type":"text","text":"邊界判斷條件"}]},{"type":"text","text":",通常情況下,我們經常使用以下幾種判斷條件:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果鏈表爲空時,代碼是否能正常工作?"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果鏈表只包含一個結點時,代碼是否能正常工作?"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果鏈表只包含兩個結點時,代碼是否能正常工作?"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"代碼邏輯在處理頭結點和尾結點的時候,是否能正常工作?"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這些判斷條件需要結合自己的實際場景來使用"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"2、必須掌握的幾類題目"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在上面的學習中,我們對鏈表的一些易錯的概念進行了解析,下面,我們就真正的代碼實踐,我在LeetCode上刷題時發現,鏈表題目通常分爲以下幾類:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"單鏈表的反轉(LeetCode206)"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"鏈表中環的檢測(LeetCode141)"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"兩個有序鏈表的合併(LeetCode21)"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"刪除鏈表(LeetCode18)"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"刪除鏈表倒數第n個結點(LeetCode19)"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"求鏈表的中間結點(LeetCode876)"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這幾類鏈表題基本涵蓋了"},{"type":"codeinline","content":[{"type":"text","text":"大部分知識點"}]},{"type":"text","text":",在下面的學習中,我們將一一攻克它,相信掌握它們之後,在以後"},{"type":"codeinline","content":[{"type":"text","text":"筆試/面試"}]},{"type":"text","text":"中,更能隨心所欲。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2.1單鏈表反轉(LeetCode206)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"思路"},{"type":"text","text":":從前往後將每個節點的指針反向,即.next內的地址換成前一個節點的,但爲了防止後面鏈表的丟失,在每次換之前需要先創建個指針指向下一個節點。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"class Solution {\n public ListNode reverseList(ListNode head) {\n\nif(head==null||head.next==null){\nreturn head;\n}\n ListNode p1=head;\n //用一個新的鏈表\n ListNode p2=null;\n while(p1!=null){\n //每次更換指向之前都需要保存下一個節點\n ListNode temp=p1.next;\n p1.next=p2;\n p2=p1;\n p1=temp;\n }\n return p2;\n }\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2.2鏈表中環的檢測(LeetCode141)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"思路"},{"type":"text","text":":定義兩個指針,p1和p2,指針p1每次走一步,指針p2每次走兩步,如果鏈表中存在環,則必然會在某個時刻滿足p1==p2"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"public class Solution {\n public boolean hasCycle(ListNode head) {\n if(head==null||head.next==null){\n return false;\n }\n ListNode slow=head;\n ListNode fast=head.next;\n while(fast!=null&&fast.next!=null){\n if(slow==fast){\n return true;\n }\n slow=slow.next;\n fast=fast.next.next;\n }\n return false;\n }\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"NOTE"},{"type":"text","text":":對於快指針來說,因爲一次跳兩步,如果要使用快指針作爲判斷條件,fast和fast.next都需要判斷是否爲空。("},{"type":"codeinline","content":[{"type":"text","text":"不可跨級"}]},{"type":"text","text":")"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2.3兩個有序的鏈表合併(LeetCode21)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"思路"}]},{"type":"text","text":":可以新創建一個鏈表用於合併後的結果,合併的條件如下"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"兩個鏈表都不爲空"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":">定義一個指針,查找合適的節點並放入新創建鏈表的下一位置"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"有一個鏈表爲空"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":">將不爲空的鏈表放入新創建鏈表的下一位置"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"class Solution {\n public ListNode mergeTwoLists(ListNode l1, ListNode l2) {\n\n if(l1==null){\n return l2;\n }\n if(l2==null){\n return l1;\n }\n ListNode result=new ListNode(0);\n ListNode temp=result;\n //兩個鏈表都不爲空\n while(l1!=null&&l2!=null){\n if(l1.val<=l2.val){\n temp.next=l1;\n temp=temp.next;\n l1=l1.next;\n }\n else{\n temp.next=l2;\n temp=temp.next;\n l2=l2.next;\n }\n }\n //有一個鏈表爲空\n if(l1==null){\n temp.next=l2;\n }\n else{\n temp.next=l1;\n }\n\n return result.next;\n }\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2.4刪除鏈表(LeetCode18)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"思路"},{"type":"text","text":":可以在鏈表頭加一個哨兵(頭結點),刪除鏈表時先找到刪除鏈表的上一個位置,按照刪除規則刪除即可。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"class Solution {\n public ListNode deleteNode(ListNode head, int val) {\n if(head==null){\n return null;\n }\n //定義一個哨兵作爲傳入鏈表的頭結點\n ListNode pre =new ListNode(0);\n pre.next=head;\n \n ListNode temp=pre;\n while(temp!=null){\n if(temp.next.val==val){\n temp.next=temp.next.next;\n break;\n }\n else{\n temp=temp.next;\n }\n }\n return pre.next;\n }\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2.5刪除鏈表倒數第 n 個結點(LeetCode19)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"思路"},{"type":"text","text":":刪除節點時要利用好"},{"type":"codeinline","content":[{"type":"text","text":"哨兵"}]},{"type":"text","text":"(帶頭結點的鏈表)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":">* 遍歷數組的長度count"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":">* 找到要刪除節點的前一個位置count-n-1"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":">* 刪除節點"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"class Solution {\n public ListNode removeNthFromEnd(ListNode head, int n) {\n ListNode pre=new ListNode(0);\n pre.next=head;\n ListNode temp1=pre;\n ListNode temp2=pre;\n int count=0;\n while(temp1!=null){\n temp1=temp1.next;\n count++;\n }\n\n while(count-n-1>0){\n temp2=temp2.next;\n count--;\n }\n temp2.next=temp2.next.next;\n \n return pre.next;\n }\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2.6求鏈表的中間結點(LeetCode876)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"思路"},{"type":"text","text":":找出鏈表中結點的個數count,然後count/2找出中間結點,刪除即可。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"class Solution {\n public ListNode middleNode(ListNode head) {\n if(head==null) return null;\n ListNode temp=head;\n int count=0;\n while(temp!=null){\n temp=temp.next;\n count++;\n }\n int mid=count/2;\n ListNode result=head;\n while(mid>0){\n result=result.next;\n mid--;\n }\n return result;\n }\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"Note"},{"type":"text","text":":實踐是檢驗真理的唯一標準,要真正的學好鏈表這個知識點,僅僅學理論是不可靠的,我們需要"},{"type":"codeinline","content":[{"type":"text","text":"多敲代碼"}]},{"type":"text","text":","},{"type":"codeinline","content":[{"type":"text","text":"多思考"}]},{"type":"text","text":","},{"type":"codeinline","content":[{"type":"text","text":"多寫多練"}]},{"type":"text","text":",針對抽象的題目,可以"},{"type":"codeinline","content":[{"type":"text","text":"舉例畫圖"}]},{"type":"text","text":",來輔助的自己的思考。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"3、學習鏈表的體會"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1、 函數中需要移動鏈表時,最好"},{"type":"codeinline","content":[{"type":"text","text":"新建一個指針來移動"}]},{"type":"text","text":",以免更改原始指針位置。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2、 單鏈表有"},{"type":"codeinline","content":[{"type":"text","text":"帶頭節點"}]},{"type":"text","text":"和"},{"type":"codeinline","content":[{"type":"text","text":"不帶頭結點"}]},{"type":"text","text":"的鏈表之分,一般做題"},{"type":"codeinline","content":[{"type":"text","text":"默認頭結點是有值的"}]},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"3、 鏈表的內存時"},{"type":"codeinline","content":[{"type":"text","text":"不連續"}]},{"type":"text","text":"的,一個節點佔一塊內存,每塊內存中有一塊位置(next)存放下一節點的地址。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"3、 鏈表中找"},{"type":"codeinline","content":[{"type":"text","text":"環"}]},{"type":"text","text":"的思想:"},{"type":"codeinline","content":[{"type":"text","text":"快慢指針"}]},{"type":"text","text":",創建兩個指針,"},{"type":"codeinline","content":[{"type":"text","text":"一個快指針:一次走兩步"}]},{"type":"text","text":","},{"type":"codeinline","content":[{"type":"text","text":"一個慢指針:一次走一步"}]},{"type":"text","text":",若相遇則有環,若指向null則無環。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"4、 鏈表找"},{"type":"codeinline","content":[{"type":"text","text":"倒數第k個節點思想"}]},{"type":"text","text":":創建"},{"type":"codeinline","content":[{"type":"text","text":"兩個指針"}]},{"type":"text","text":",第一個指針查詢鏈表中結點的個數"},{"type":"codeinline","content":[{"type":"text","text":"count"}]},{"type":"text","text":",然後"},{"type":"codeinline","content":[{"type":"text","text":"count-k"}]},{"type":"text","text":"確定刪除結點的位置,用第二個指針遍歷鏈表到"},{"type":"codeinline","content":[{"type":"text","text":"count-n-1"}]},{"type":"text","text":"個位置。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"5、 反向鏈表思想:"},{"type":"codeinline","content":[{"type":"text","text":"從前往後"}]},{"type":"text","text":"將每個節點的指針反向,"},{"type":"codeinline","content":[{"type":"text","text":"即next內的地址換成前一個節點的"}]},{"type":"text","text":",但爲了防止後面鏈表的丟失,在每次換之前需要"},{"type":"codeinline","content":[{"type":"text","text":"先創建個指針指向下一個節點"}]},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"總結"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"無論學習任何一個知識點,我們都需要在掌握"},{"type":"codeinline","content":[{"type":"text","text":"術(使用方法)"}]},{"type":"text","text":"的基礎上,學習"},{"type":"codeinline","content":[{"type":"text","text":"道(本源)"}]},{"type":"text","text":",學習數據結構與算法也是一樣,我們不僅要掌握"},{"type":"codeinline","content":[{"type":"text","text":"如何使用它"}]},{"type":"text","text":",更要掌握"},{"type":"codeinline","content":[{"type":"text","text":"爲什麼要是用它"}]},{"type":"text","text":",相比其它的方法,"},{"type":"codeinline","content":[{"type":"text","text":"它有什麼優點"}]},{"type":"text","text":",難道是"},{"type":"codeinline","content":[{"type":"text","text":"時間複雜度低"}]},{"type":"text","text":","},{"type":"codeinline","content":[{"type":"text","text":"空間複雜度小"}]},{"type":"text","text":",還是它的數據結構"},{"type":"codeinline","content":[{"type":"text","text":"適合這個場景等等"}]},{"type":"text","text":"..."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"參考文獻"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"[1]王爭.數據結構與算法之美"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"[2]LeetCode中國網站"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"刷題組合拳推薦"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"筆者在過去的3個月時間裏整理常用的"},{"type":"codeinline","content":[{"type":"text","text":"數據結構與算法"}]},{"type":"text","text":"和"},{"type":"codeinline","content":[{"type":"text","text":"秒殺劍指offer"}]},{"type":"text","text":",公衆號分別回覆"},{"type":"codeinline","content":[{"type":"text","text":"數據結構與算法"}]},{"type":"text","text":","},{"type":"codeinline","content":[{"type":"text","text":"秒殺劍指offer"}]},{"type":"text","text":",即可領取兩套電子書,希望能夠幫助大家。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/1a/1ae1dba8ace02f8f893ab20b15cecbba.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/6c/6c27702bae816147b22b79ffc0a6acb8.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我是"},{"type":"codeinline","content":[{"type":"text","text":"Simon郎"}]},{"type":"text","text":",一個想要每天博學一點點的小青年,關注我,讓我們一起進階,一起博學。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/95/956573d023ad43fa3e2e6b8f5e6cecb0.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章