问题描述
给定一个链表的头指针 pHead 和一个整数值 x,要求将链表分割成两部分。所有小于 x 的结点排在大于或等于 x 的结点之前,且不能改变原来数据的相对顺序。返回分割后的新链表的头指针。
核心要求:
- 时间复杂度为
O(n) - 空间复杂度为
O(1)
思路分析
这道题的核心在于如何高效地重组链表而不破坏原有顺序。如果直接原地修改指针,逻辑会非常复杂,容易出错。比较稳妥的做法是构建两条新的子链表:一条存放小于 x 的节点,另一条存放大于等于 x 的节点。
为了简化边界处理(比如空链表、第一个节点就满足条件等),我们引入两个哨兵节点(Dummy Node)作为虚拟头结点。这样在尾插操作时,无需判断当前是否为头节点,统一由哨兵位接管。
具体步骤如下:
- 初始化:创建
guardLess和guardGreater两个哨兵节点,分别对应两条子链表的头部。同时维护两个尾指针lessTail和greaterTail,初始指向各自的哨兵节点。 - 遍历:使用移动指针
curNode扫描原链表。根据节点值与x的比较结果,将节点尾插到对应的子链表中,并更新相应的尾指针。 - 连接:遍历结束后,将
lessTail->next指向guardGreater->next,完成两条链表的拼接。 - 收尾:务必将新链表的最后一个节点(即
greaterTail)的next置为nullptr,防止形成环。最后释放哨兵节点内存,返回guardLess->next作为新头指针。
代码实现
class Partition {
public:
ListNode* partition(ListNode* pHead, int x) {
if (pHead == nullptr) return nullptr;
// 创建哨兵节点,避免处理头指针为空的情况
ListNode* guardLess = new ListNode(-1);
ListNode* guardGreater = new ListNode(-1);
// 维护两个子链表的尾指针
ListNode* lessTail = guardLess;
ListNode* greaterTail = guardGreater;
ListNode* curNode = pHead;
while (curNode) {
(curNode->val < x) {
lessTail->next = curNode;
lessTail = lessTail->next;
} {
greaterTail->next = curNode;
greaterTail = greaterTail->next;
}
curNode = curNode->next;
}
lessTail->next = guardGreater->next;
greaterTail->next = ;
pHead = guardLess->next;
guardGreater;
guardLess;
pHead;
}
};


