leetcode 鏈表系列

1、 反轉鏈表

https://leetcode.com/problems/reverse-linked-list/solution/

Assume that we have linked list 1 → 2 → 3 → Ø, we would like to change it to Ø ← 1 ← 2 ← 3.

While you are traversing the list, change the current node’s next pointer to point to its previous element. Since a node does not have reference to its previous node, you must store its previous element beforehand. You also need another pointer to store the next node before changing the reference. Do not forget to return the new head reference at the end!

  • 當要反轉鏈表的時候,需要改變當前節點的後繼節點指針指向當前節點的前驅節點,由於在單鏈表中一個節點不會保存他的前驅節點,所以需要一個臨時變量來保存他的前驅節點(pre)
  • 同樣需要另一個指針(temp)來保存當前節點的後繼節點,否則在你反轉指向(當前節點的後繼節點指針指向當前節點的前驅節點)以後,鏈表就斷了
  • 最後需要返回的是pre 指針
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode pre = null;
        ListNode current = head;
        ListNode temp = null;
        while(current != null){
            temp = current.next;
            current.next = pre;
            pre = current;
            current = temp;
        }
        return pre;
    }
}

2、 鏈表中間段逆序

https://leetcode.com/problems/reverse-linked-list-ii/

  • 找出四個關鍵節點,當逆序完成後把逆序的那部分連接回原來的鏈表
  • 將head節點移動m-1次,到開始逆序的節點
  • 將中間段逆序
  • 拼接逆序的鏈表和原來的鏈表
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseBetween(ListNode head, int m, int n) {
        int changeLength = n - m + 1;
        ListNode resultHead = head;
        ListNode preHead = null;
        while(head != null  && ((m-1) > 0)){
            preHead = head;
            head = head.next;
            m--;
        }
        ListNode modify_last_tail = head;
        ListNode new_head = null;
        while(head != null && changeLength > 0){
            ListNode next = head.next;
            head.next = new_head;
            new_head = head;
            head = next;
            changeLength --;
        }
        modify_last_tail.next = head;
        if(preHead != null){
            preHead.next = new_head;
        }else{
            resultHead = new_head;
        }
        return resultHead;
    }
}

3、 合併有序鏈表

https://leetcode.com/problems/merge-two-sorted-lists/

  • 首先需要一個頭節點來保存新鏈表的頭
  • 需要有兩個指針分別指向兩個鏈表
  • 還需要一個指針來操縱新鏈表,控制新節點的加入
  • 判斷兩個鏈表頭結點誰小,誰就轉移到新鏈表的最後
  • 被轉移頭結點的鏈表的首指針向後移動一下
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode head = new ListNode(0);
        ListNode pre = head;
        while(l1 != null && l2 != null){
            if(l1.val <= l2.val){
                pre.next = l1;
                l1 = l1.next;
            }else{
                pre.next = l2;
                l2 = l2.next;
            }
            pre = pre.next;
        }
        if(l1 != null){
            pre.next = l1;
        }
        if(l2 != null){
            pre.next = l2;
        }
        return head.next;
    }
}

4、求兩個鏈表的交叉點

https://leetcode.com/problems/intersection-of-two-linked-lists/

  • 最直觀的方法就是把一個鏈表放入set ,遍歷另一個鏈表,每個節點都去set中判斷,是否存在,這個太簡單直接忽略
  • 如果不能用set,從題目給定的情境下去挖掘潛在的邏輯就是如果兩個鏈表有交叉點,那說明從交叉點以後,鏈表是重合的,也就是說交叉點只可能出現在倒數m(n 代表長鏈表的長度,m代表短鏈表長度)個節點之內,那我們可以去把兩個鏈表的頭結點去對齊,將較長鏈表的頭指針移動到和短鏈表頭指針對其的地方,再同步向後遍歷比較
    /**
  • Definition for singly-linked list.

  • public class ListNode {

  • int val;
    
  • ListNode next;
    
  • ListNode(int x) {
    
  •     val = x;
    
  •     next = null;
    
  • }
    
  • }
    */
    public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    int lengthA = getLengthOfList(headA);
    int lengthB = getLengthOfList(headB);
    if(lengthA >= lengthB){
    headA = forwardList(headA,lengthA - lengthB);
    }else{
    headB = forwardList(headB,lengthB - lengthA);
    }
    ListNode intersection = null;
    while(headA != null){
    if(headA == headB){
    return headA;
    }
    headA = headA.next;
    headB = headB.next;
    }
    return null;
    }

    public ListNode forwardList(ListNode head,int step){
    while(step > 0){
    head = head.next;
    step --;
    }
    return head;
    }

    public int getLengthOfList(ListNode head){
    int length = 0;

     while(head != null){
         head = head.next;
         length ++;
     }
     return length;
    

    }
    }

5、判斷鏈表是否有環

https://leetcode.com/problems/linked-list-cycle-ii/

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