題目描述:給定一個鏈結串列的頭節點 head 和一個整數 x,請重新排列串列,使得所有值小於 x 的節點排在所有值大於或等於 x 的節點之前,同時保留每一組內部節點的相對順序,並返回重排後的頭節點。
解題思路:
核心想法是「分成兩條子串列,再合併」:
lessHead(虛擬頭)串接所有值 < x 的節點;greaterHead(虛擬頭)串接所有值 >= x 的節點。使用虛擬頭可避免空串列的邊界判斷。< x,接到 less 子串列尾端;否則接到 greater 子串列尾端。由於是依序走訪,相對順序自然保留。less 子串列的尾節點的 next 指向 greaterHead->next(greater 子串列的實際起點),並將 greater 子串列的尾節點的 next 設為 nullptr 以避免成環。lessHead->next 作為新頭節點。此方法一次走訪即可完成,邏輯清晰,且完全保留相對順序。
時間複雜度:O(n) — 只需一次線性走訪原串列,每個節點恰好被處理一次,n 為節點總數。
空間複雜度:O(1) — 只使用兩個虛擬頭節點和幾個指標變數,不需要額外的動態記憶體配置(節點本身是就地重新串接)。
1. Create two dummy nodes: lessHead and greaterHead. 2. Set less = lessHead, greater = greaterHead, cur = head. 3. While cur is not null: a. If cur.val < x: append cur to the less list (less.next = cur; less = cur). b. Else: append cur to the greater list (greater.next = cur; greater = cur). c. Advance cur = cur.next. 4. Set greater.next = null (terminate the greater list). 5. Set less.next = greaterHead.next (join the two lists). 6. Return lessHead.next.
方法一:原地交換(in-place swap)
使用兩個指標在原串列上直接尋找不符合分區條件的節點並交換其值(而非重新串接指標)。時間複雜度 O(n²)(每次找到需要移動的節點都可能要走訪串列),空間複雜度 O(1)。此方法較難保證穩定的相對順序,且效率低,不推薦用於正式解答。
方法二:收集值後重建
兩次走訪:第一次將所有 < x 的值存入 vector,第二次將所有 >= x 的值存入,然後按順序填回原串列節點的 val。時間複雜度 O(n),空間複雜度 O(n)。優點是邏輯最簡單,缺點是需要 O(n) 額外空間且不能處理節點本身需要移動的泛化情境。
< x、值 == x、值 > x),如何擴展現有解法?需要新增幾個虛擬頭節點,合併時順序又是什麼?prev 指標)?合併時又需要注意哪些邊界條件?