LeetCode連結串列常用技巧(一)
阿新 • • 發佈:2021-11-02
連結串列遍歷
單鏈表中的每個結點不僅包含值,還包含連結到下一個結點的地址。通過這種方式,單鏈表將所有結點按順序組織起來。所以我們對連結串列的遍歷可以通過兩種方式:迭代或者遞迴
我們約定連結串列結構如下:
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;
}
}