1. 程式人生 > 其它 >LeetCode連結串列常用技巧(一)

LeetCode連結串列常用技巧(一)

連結串列遍歷

單鏈表中的每個結點不僅包含值,還包含連結到下一個結點的地址。通過這種方式,單鏈表將所有結點按順序組織起來。所以我們對連結串列的遍歷可以通過兩種方式:迭代或者遞迴

我們約定連結串列結構如下:

public class ListNode {
    int val;
    ListNode next;
    ListNode() {}
    ListNode(int val) { this.val = val; }
    ListNode(int val, ListNode next) { this.val = val; this.next = next; }
}

迭代遍歷程式碼:

public void list(ListNode head){
    if(head == null){
        return;
    }
    while(head != null){
        System.out.println(head);
        head = head.next;
    }
}

遞迴遍歷

public void list(ListNode head){
    if(head == null){
        return;
    }
    System.out.println(head);
    list(head.next);
}

連結串列部分反轉

LeetCode92題:
給你單鏈表的頭指標 head 和兩個整數 left 和 right ,其中 left <= right 。請你反轉從位置 left 到位置 right 的連結串列節點,返回 反轉後的連結串列 。

我們先考慮反轉整個連結串列,然後一步一步推匯出反轉連結串列部分。

對於整個連結串列的反轉我們有兩種方式,迭代或者遞迴

//迭代
public ListNode reverse(ListNode head){
    if(head == null || head.next == null){//當連結串列為空或者只有一個元素的時候
        return head;
    }
    //pre為當前節點前一個節點,當前節點,next下一個節點
    ListNode pre = null,cur = head,next = head;
    while(cur != null){
       	next = cur.next;//獲取當前節點下一個節點
        cur.next = pre;//將當前節點的下一個節點設定為前一個節點
        pre = cur;//將前一個節點後移
        cur = next;  //當前節點後移 
    }    
    return pre;   
}

//遞迴
public ListNode reverse(ListNode head){
    if(head.next == null){
        return head;
    }
    ListNode last = reverse(head.next);//遞迴
    head.next.next = head;
    head.next = null;
    return last;
}

反轉連結串列的前k個節點

//遞迴反轉單鏈表以head為頭節點前k個
ListNode successor = null;
public ListNode reverseK(ListNode head,int k){
    if(k == 1){
        successor = head.next;
        return head;
    }

    ListNode last = reverseK(head.next,k-1);
    head.next.next = head;
    head.next = successor;
    return last;
}

反轉連結串列的一部分

public ListNode reverseBetween(ListNode head, int left, int right) {
    if(head == null || right - left == 0){
        return head;
    }
    ListNode cur = head;
    ListNode pre = null;
    for(int i = 1; i < left;i++){
        pre = cur;
        cur = cur.next;
    }
    if(pre == null){
        head = reverseK(head,right - left + 1);
    }else{
        pre.next = reverseK(cur,right - left + 1);
    }
    return head;

}

合併兩個有序連結串列

將兩個升序連結串列合併為一個新的 升序 連結串列並返回。新連結串列是通過拼接給定的兩個連結串列的所有節點組成的。

//迭代遍歷實現
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
    ListNode prehead = new ListNode(-1);//佔位頭指標,避免空指標
    ListNode cur = prehead;
    while(l1 != null && l2 != null){
        if(l1.val <= l2.val){
            cur.next = l1;
            l1 = l1.next;
        }else{
            cur.next = l2;
            l2 = l2.next;
        }
        cur = cur.next;
    }

    cur.next = l1 == null ? l2 : l1;

    return prehead.next;
}
//遞迴實現
 public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
     //遞迴實現
     if(l1 == null){
         return l2;
     }else if(l2 == null){
         return l1;
     }else if(l1.val <= l2.val){
         l1.next = mergeTwoLists(l1.next,l2);
         return l1;
     }else{
         l2.next = mergeTwoLists(l1,l2.next);
         return l2;
     }
 }