面试题 02.04. 分割链表 - 力扣(LeetCode)
题面:
给你一个链表的头节点 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]
提示:
- 链表中节点的数目在范围
[0, 200]
内 -100 <= Node.val <= 100
-200 <= x <= 200
思路:
这里用双指针操作,我们新建两个链表list1和list2,这次我们用哨兵位的思想,
哨兵优点就是,让头节点为空,方便头插,也不用判断头节点是否存在
设置两个链表后,让head依次后移访问数据,如果小于给定的x就给list1,反之就给list2
因为这两个新链表指针还要移动,因此要再创建两个指针保存他们的头节点的地址
代码:
typedef struct ListNode node;
struct ListNode* partition(struct ListNode* head, int x) {
//新建两个链表
node* list1 = (node*)malloc(sizeof(node));// < x
list1->next = NULL;// 给新链表置空,方便判断链表是否有效
node* list2 = (node*)malloc(sizeof(node));// >= x
list2->next = NULL;
// 保存头节点
node* newhead1 = list1;
node* newhead2 = list2;
// 读取题给链表
while (head)//如果链表为空就跳出,如果到结尾也可以跳出
{
if (head->val < x)
{
list1->next = head;
list1 = list1->next;
head = head->next;
}
else
{
list2->next = head;
list2 = list2->next;
head = head->next;
}
}
// 判断两个链表是否有效
if (newhead1->next)// 如果list1链表有效
{
list1->next = newhead2->next;// 无论list2是否有效都可以链接到list1后面
list2->next = NULL;// 这里是防止最后一个节点给了list1,list2没有尾,要NULL
return newhead1->next;// list1有效就弹出
}
return newhead2->next;// 说明list1为空。把list2弹出,
//list2要么为空,结果就是NULL,要么list2有效,list2可以读取head的尾部NULL,因此不用再赋值了
}