一、題目是啥?一句話說清
給你一個鏈表和一個值 x,把鏈表分成兩部分:所有小于 x 的節點都放在大于或等于 x 的節點之前,并且保持節點原來的相對順序。
示例:
- 輸入:head = [1,4,3,2,5,2], x = 3
- 輸出:[1,2,2,4,3,5](所有小于3的節點1、2、2都在大于等于3的節點4、3、5之前,且相對順序不變)
二、解題核心
使用兩個臨時鏈表:一個收集所有小于 x 的節點,另一個收集所有大于或等于 x 的節點。遍歷原鏈表,將每個節點分配到對應的臨時鏈表中,最后將兩個臨時鏈表連接起來。 這就像把一堆水果分成兩筐:一筐放所有蘋果,另一筐放所有橙子,然后把蘋果筐放在橙子筐前面。
三、關鍵在哪里?(3個核心點)
想理解并解決這道題,必須抓住以下三個關鍵點:
1. 兩個臨時鏈表的使用
- 是什么:創建兩個臨時鏈表,分別存儲小于 x 的節點和大于等于 x 的節點。
- 為什么重要:這樣可以保持節點的相對順序,因為節點被按順序添加到對應的鏈表中。
2. 啞節點(Dummy Node)的運用
- 是什么:為每個臨時鏈表創建一個啞節點作為頭節點,簡化鏈表操作。
- 為什么重要:啞節點可以避免處理空鏈表的邊界情況,讓代碼更簡潔。
3. 正確連接鏈表
- 是什么:遍歷完成后,將小于 x 的鏈表的末尾指向大于等于 x 的鏈表的頭節點,并將大于等于 x 的鏈表的末尾指向 null。
- 為什么重要:如果連接不正確,可能會導致鏈表斷開或形成環。
四、看圖理解流程(通俗理解版本)
讓我們用鏈表 1 → 4 → 3 → 2 → 5 → 2 和 x=3 的例子來可視化過程:
-
初始化:
- 創建兩個啞節點:leftDummy 和 rightDummy。
- 初始化兩個指針 left 和 right,分別指向 leftDummy 和 rightDummy。
- 初始狀態:leftDummy → null, rightDummy → null
-
遍歷原鏈表:
- 節點1:值1 < 3,添加到 left 鏈表:leftDummy → 1
- 節點4:值4 ≥ 3,添加到 right 鏈表:rightDummy → 4
- 節點3:值3 ≥ 3,添加到 right 鏈表:rightDummy → 4 → 3
- 節點2:值2 < 3,添加到 left 鏈表:leftDummy → 1 → 2
- 節點5:值5 ≥ 3,添加到 right 鏈表:rightDummy → 4 → 3 → 5
- 節點2:值2 < 3,添加到 left 鏈表:leftDummy → 1 → 2 → 2
-
連接鏈表:
- 將 left 鏈表的末尾(最后一個2)指向 right 鏈表的頭節點(4)。
- 將 right 鏈表的末尾(5)指向 null。
- 最終鏈表:leftDummy → 1 → 2 → 2 → 4 → 3 → 5
-
返回結果:返回 leftDummy.next,即節點1。
五、C++ 代碼實現(附詳細注釋)
#include <iostream>
using namespace std;// 鏈表節點定義
struct ListNode {int val