演算法-連結串列

濤姐濤哥發表於2021-07-15

演算法-連結串列

 

    雲想衣裳花想容,春風拂檻露華濃。

 

簡介:演算法-連結串列

一、從尾到頭列印連結串列

1、題目描述

輸入一個連結串列的頭節點,按連結串列從尾到頭的順序返回每個節點的值(用陣列返回)。
輸入:
{1,2,3}
返回值:
[3,2,1]

2、解題思路

使用遞迴

要逆序列印連結串列 1->2->3(3,2,1),可以先逆序列印連結串列 2->3(3,2),最後再列印第一個節點 1。而連結串列 2->3 可以看成一個新的連結串列,要逆序列印該連結串列可以繼續使用求解函式,也就是在求解函式中呼叫自己,這就是遞迴函式。

演算法-連結串列
 1 import java.util.*;
 2 public class Solution {
 3     public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
 4         ArrayList<Integer> ret = new ArrayList<>();
 5         if (listNode != null) {
 6             // 遞迴
 7             ret.addAll(printListFromTailToHead(listNode.next));
 8             ret.add(listNode.val);
 9         }
10         return ret;
11     }
12 }
View Code

二、刪除連結串列中重複的節點

1、題目描述

在一個排序的連結串列中,存在重複的結點,請刪除該連結串列中重複的結點,重複的結點不保留,返回連結串列頭指標。 例如,連結串列1->2->3->3->4->4->5 處理後為 1->2->5

輸入:
{1,2,3,3,4,4,5}
返回值:
{1,2,5}

2、解題思路

藉助輔助頭結點,可避免單獨討論頭結點的情況。設定兩個結點 pre 和 cur,當 cur 和 cur.next 值相等,cur 一直向前走,直到不等退出迴圈,這時候 cur 指的值還是重複值,調整 cur 和 pre 的指標再次判斷。

演算法-連結串列
 1 /*
 2 刪除連結串列中重複的結點
 3 */
 4 public class Solution {
 5     public ListNode deleteDuplication(ListNode pHead) {
 6         /*
 7         構建輔助頭結點
 8         對於連結串列而言,不儲存的意思也就是跳過這一結點next指向下一個結點
 9          */      
10         ListNode head=new ListNode(-1);
11         head.next=pHead;
12         ListNode saveHead=head;//儲存下來的結點
13         ListNode currentNode=pHead;
14         while(currentNode!=null){
15             if(currentNode.next!=null && currentNode.val==currentNode.next.val) {//有重複了,跳過
16                 while (currentNode.next != null && currentNode.val == currentNode.next.val) {
17                     currentNode = currentNode.next;//跳過這些相同結點
18                 }
19                 currentNode=currentNode.next;//有重複,一個都不儲存
20                 saveHead.next=currentNode;//儲存
21             }
22             else {
23                 //這裡是沒重複的
24                 saveHead=currentNode;
25                 currentNode=currentNode.next;
26             }
27         }
28         return head.next;
29     }
30 }
View Code

三、連結串列中倒數第K 個結點

1、題目描述

輸入一個連結串列,輸出一個連結串列,該輸出連結串列包含原連結串列中從倒數第k 個結點至尾節點的全部節點。如果該連結串列長度小於k,請返回一個長度為 0 的連結串列。
輸入:
{1,2,3,4,5},1 
返回值:
{5}

2、解題思路

在連結串列中:倒數的+順數的長度等於連結串列總長度,所以可以設定兩個指標,一個先走K 步,剩下的到連結串列的末尾要走的步數就是倒數第k個節點,需要從頭開始走的步數。

演算法-連結串列
 1 import java.util.*;
 2 
 3 /*
 4  連結串列中倒數最後k 個結點
 5  */
 6 public class Solution {
 7     public ListNode FindKthToTail (ListNode pHead, int k) {       
 8         ListNode first = pHead;
 9         for(int i = 0; i < k; i++){
10             if(first == null){
11                 return first;
12             }
13             first = first.next;
14         }
15         ListNode last = pHead;
16         while(first != null){
17             first = first.next;
18             last = last.next;
19         }
20         return last;
21     }
22 }
View Code

四、連結串列中環的入口結點

1、題目描述

給一個連結串列,若其中包含環,請找出該連結串列的環的入口結點,否則,返回null。
輸入:
{1,2},{3,4,5}
返回值:
3
說明:
返回環形連結串列入口節點,我們後臺會列印該環形連結串列入口節點,即3 

2、解題思路

使用雙指標,一個快指標 fast 每次移動兩個節點,一個慢指標 slow 每次移動一個節點。因為存在環,所以兩個指標必定相遇在環中的某個節點上。

假設環入口節點為 y1,相遇所在節點為 z1。

假設快指標 fast 在圈內繞了 N 圈,則總路徑長度為 x+Ny+(N-1)z。z 為 (N-1) 倍是因為快慢指標最後已經在 z1 節點相遇了,後面就不需要再走了。

而慢指標 slow 總路徑長度為 x+y。

因為快指標是慢指標的兩倍,因此 x+Ny+(N-1)z = 2(x+y)。

我們要找的是環入口節點 y1,也可以看成尋找長度 x 的值,因此我們先將上面的等值分解為和 x 有關:x=(N-2)y+(N-1)z。

上面的等值沒有很強的規律,但是我們可以發現 y+z 就是圓環的總長度,因此我們將上面的等式再分解:x=(N-2)(y+z)+z。這個等式左邊是從起點x1 到環入口節點 y1 的長度,而右邊是在圓環中走過 (N-2) 圈,再從相遇點 z1 再走過長度為 z 的長度。此時我們可以發現如果讓兩個指標同時從起點 x1 和相遇點 z1 開始,每次只走過一個距離,那麼最後他們會在環入口節點相遇。

演算法-連結串列
 1 /*
 2 連結串列中環的入口結點
 3 */
 4 public class Solution {
 5 
 6     public ListNode EntryNodeOfLoop(ListNode pHead) {
 7         if(pHead == null || pHead.next == null){
 8             return null;
 9         }
10         ListNode slow = pHead;
11         ListNode fast = pHead;
12         do{
13             fast = fast.next.next;
14             slow = slow.next;
15         }while(slow != fast);
16         fast = pHead;
17         while(slow != fast){
18             slow = slow.next;
19             fast = fast.next;
20         }
21         return slow;       
22     }
23 }
View Code

五、連結串列中環的入口結點

1、題目描述

輸入一個連結串列,反轉連結串列後,輸出新連結串列的表頭。
輸入:
{1,2,3}
返回值:
{3,2,1}

2、解題思路

遞迴

演算法-連結串列
 1 /*
 2 反轉連結串列
 3 */
 4 public class Solution {
 5     public ListNode ReverseList(ListNode head) {
 6         if(head == null || head.next == null){
 7             return head;
 8         }
 9         ListNode next = head.next;      
10         // 遞迴
11         ListNode newHead = ReverseList(next);
12         next.next = head;
13         head.next = null;
14         return newHead;
15     }
16 }
View Code

 

 

 

 

雲想衣裳花想容

    春風拂檻露華濃

 

 

 

 

 

相關文章