LeetCode143——重排連結串列
我的LeetCode程式碼倉:https://github.com/617076674/LeetCode
原題連結:https://leetcode-cn.com/problems/reorder-list/description/
題目描述:
知識點:雙指標、連結串列
思路:用快慢雙指標遍歷連結串列區分連結串列的前半部分和後半部分
借鑑LeetCode141——環形連結串列和LeetCode142——環形連結串列II中的思路二,我們用快慢雙指標遍歷連結串列以區分連結串列的前半部分和後半部分。參照程式碼,慢指標cur2移動一步,則快指標cur3移動2步。
以示例1為例(連結串列中節點個數是偶數個):-1
以示例2為例(連結串列中節點個數是奇數個):-1 -> 1 -> 2 -> 3 -> 4 -> 5,其中-1是我們設立的虛擬頭節點,也是cur2和cur3指標的共同起點。當cur3到達4節點時,遍歷結束,此時cur2在3節點,其後半部分節點也從cur2.next節點開始。
因此無論連結串列中節點個數的奇偶性,在cur2和cur3移動結束後,其後半部分節點均是從cur2.next節點開始的。
我們將連結串列分成兩部分,第一部分是cur2.next節點之前的節點,第二部分是cur2.next及其之後的節點。
接下來我們只需反轉第二部分節點,關於反轉連結串列的方法,可以參考LeetCode206——反轉連結串列,本題的實現中使用了非遞迴的方式反轉連結串列。
最後,我們只需根據題意,用兩部分節點拼接出我們需要的新連結串列即可。
時間複雜度是O(n),其中n為連結串列中的節點個數。空間複雜度是O(1)。
JAVA程式碼:
public class Solution { public void reorderList(ListNode head) { //設立虛擬頭節點 ListNode dummyHead = new ListNode(-1); dummyHead.next = head; //cur1指向連結串列頭節點 ListNode cur1 = head; //cur2,cur3是快慢雙指標,cur2移動一步,cur3移動兩步 ListNode cur2 = dummyHead; ListNode cur3 = dummyHead; while(cur3 != null && cur3.next != null) { cur2 = cur2.next; cur3 = cur3.next.next; } cur2 = cur2.next; //尋找cur2的父節點preCur2 ListNode preCur2 = dummyHead; while(preCur2.next != cur2) { preCur2 = preCur2.next; } preCur2.next = null; //反轉後半段連結串列 ListNode newHead = reverseLinkedList(cur2); ListNode newCur1 = newHead; //組合出新連結串列 while(cur1 != null && newCur1 != null) { ListNode nextCur1 = cur1.next; ListNode nextNewCur1 = newCur1.next; cur1.next = newCur1; newCur1.next = nextCur1; newCur1 = nextNewCur1; cur1 = nextCur1; } } private ListNode reverseLinkedList(ListNode head) { if(head == null || head.next == null) { return head; } ListNode pre = null; ListNode cur = head; ListNode next = cur.next; while(cur != null) { cur.next = pre; pre = cur; cur = next; if(cur != null) { next = cur.next; } } return pre; } }
LeetCode解題報告: