LeetCode.02.04.分割链表
分割链表
给你一个链表的头节点 head
和一个特定值 x
,请你对链表进行分隔,使得所有 小于 x
的节点都出现在 大于或等于 x
的节点之前。
你不需要 保留 每个分区中各节点的初始相对位置。
示例 1:
输入:head = [1,4,3,2,5,2], x = 3
输出:[1,2,2,4,3,5]
示例 2:
输入:head = [2,1], x = 2
输出:[1,2]
解题思路:
使用双指针的思路来解决链表分区问题,通过创建两个新链表分别存储小于 x
和大于等于 x
的节点,最后合并这两个链表得到结果。
- 虚拟头节点初始化:分别为值小于
x
和大于等于x
的节点创建虚拟头节点head1
和head2
,并将它们的next
指针初始化为NULL
。 - 遍历原链表:遍历原链表,根据节点值与
x
的大小关系,将节点连接到对应的链表尾部。 - 断开节点连接:在将节点连接到新链表后,断开该节点与原链表的连接,避免形成环。
- 合并链表:将存储大于等于
x
节点的链表连接到存储小于x
节点的链表尾部。 - 释放虚拟头节点:释放创建的两个虚拟头节点。
- 返回结果:返回合并后链表的头节点。
struct ListNode* partition(struct ListNode* head, int x) {
// 小的放 list1,大的放 list2
struct ListNode* head1,* tail1,* head2,* tail2;
head1 = tail1 = (struct ListNode*)malloc(sizeof(struct ListNode));
head2 = tail2 = (struct ListNode*)malloc(sizeof(struct ListNode));
// 初始化虚拟头节点的 next 指针
head1->next = NULL;
head2->next = NULL;
struct ListNode* cur = head;
while (cur) {
struct ListNode* next = cur->next; // 保存当前节点的下一个节点
if (cur->val < x) {
tail1->next = cur;
tail1 = tail1->next;
tail1->next = NULL; // 断开当前节点与原链表的连接
} else {
tail2->next = cur;
tail2 = tail2->next;
tail2->next = NULL; // 断开当前节点与原链表的连接
}
cur = next;
}
tail1->next = head2->next;// 合并两个链表
struct ListNode* result = head1->next;// 保存结果链表头节点
free(head1);// 释放虚拟头节点
free(head2);
return result;
}