【鏈表】反轉一個單向鏈表

在這裏插入圖片描述

第一步:定義一個單向鏈表

 public class ListNode {
       //用來存放當前節點的數據值
       int val;
       //用來指向下一個節點的引用,其實說的C裏面的指針就是Java中的引用。
       因爲我們如何來讓一個個對象在內存關聯起來,需要通過引用地址來依賴。
      ListNode next;
      //value數據值的賦值直接通過構造函數賦值,不需要set
      ListNode(int x) { val = x; }
 }

思考思路:
1、反轉的邊界條件:1個數據都沒有的情況,只有2個的情況
在這裏插入圖片描述
那麼我們先來看下默認情況下的鏈表,根據上面的類構造出的對象,在內存中是不連續分配的爲什麼不連續呢?有人思考過沒有,因爲他們都有自己的特定的引用地址。那麼鏈表的意義是什麼呢?就是將一個個對象像一個鏈子一樣串聯起來。形成一個數據結構。這樣的話是不是好理解了?那麼以我而言老師們整天說指針,我以爲必須學好C語言,實際上目前來看Java語言你也可以理解這些數據結構。比如說指針的移動其實就是引用地址的賦值改變。比如我上面的圖你可以看到的是有跟線沒有按照正常的連接,導致那個線很長,實際上我只是形象話的畫圖而已。相當於如果正常的邏輯是依次連接很規整,但是實際上如果我們中間插入節點,或者刪除節點,那麼就可能導致這樣的情況。第二個value值存儲的是相當於自己本身的值,next屬性其實相當於存儲的是下個節點的引用地址,通過這樣的依賴,形成一個鏈表。

那麼代碼我們怎麼來實現呢?通過上面的圖解我們可以編碼按照剛纔的思路,邊界檢查,代碼書寫。
在這裏插入圖片描述
在這裏插入圖片描述
現在我們用代碼實現下上面的思路:

public ListNode reverseListNode(ListNode head){
//1、定義一個新的頭節點信息初始爲null
ListNode prev = null;
//2、定義能夠拆分鏈表爲2端的當前遊標節點,開始的時候爲首節點head;
ListNode curr = head;
//3、我們根據思路需要一個個節點進行迭代,基於上面的圖解我們知道其實通過一個head節點就可以獲取所有的信息只要不斷next就可以,如果next沒有引用爲null說明走到了尾節點。
while(curr.next != null){
//根據上面講的1-》2和2-》1我們知道會截斷2部分,這個時候需要緩存臨時變量部分,防止引用斷開,我們找不到可達性gcroot分析找不到就被GC了
ListNode tempHead = curr.next;
//現在我們拆分爲2部分,一部分爲curr,一部分爲curr.next現在稱爲tempHead;
//將新的頭節點信息賦值給當前節點的引用,第一次是將curr的next置爲null,第二次直接將新的鏈表賦值給當前遊標節點
curr.next =prev;
//交換數據,現在的狀態其實相當於圖的第二步驟後的效果圖,然後爲了省略掉第三步驟,這裏做了個小變動就是直接將當前這個遊標節點賦值給prev新的頭節點。這樣就少了一步賦值
prev = curr;
//完成了上面的交換,
步驟第一次循環:現在分爲2部分,prev: 1-》null, tempHead: 2-》3-》4-》5-》null
步驟第二次循環:現在分爲2部分交換的時候相當於2與1的交換,prev: 2-》1-》null, tempHead: 3-》4-》5-》null
步驟第三次循環:現在分爲2部分交換的時候相當於2與1的交換,prev: 3-》2-》1-》null, tempHead: 4-》5-》null
步驟第四次循環:現在分爲2部分交換的時候相當於2與1的交換,prev: 4-》 3-》2-》1-》null, tempHead:5-》null
步驟第五次循環:現在分爲2部分交換的時候相當於2與1的交換,prev: 5-》4-》3-》2-》1-》null, tempHead: null
步驟第六次循環:由於null退出循環條件。
//爲了遍歷下一個節點則我們這邊重新定義當前的遊標節點爲tempHead
curr = tempHead;
}
//當所有的步驟都完成以後,我們就知道了prev是我們需要的東西。
return prev;
}
時間複雜度:O(n),空間複雜度:O(1);

這裏是引用

//遞歸代碼
public ListNode reverseListNode(ListNode head){
//遞歸主要需要做好邊界處理
if(head == null || head.next == null){
return head;
}
//虛擬棧遞歸
ListNode newHead = reverseListNode(head.next);
//出棧倒序執行,用指針引用指向頭尾相連,然後幹掉原來的每個棧的首節點,則每個棧的首節點變爲尾節點。
head.next.next = head;
head.next =null;
//最後只需要返回新的節點就可以啦。
return newHead;

}
時間複雜度O(n),因爲我剛纔圖上也講了需要用到虛擬棧,所以空間複雜度爲O(n)

原題:反轉一個單向鏈表

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章