零、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
三、解题思路
- 基本思路:
分隔+合并;将满足条件的结点聚在一起,最后连接两个链表; - 具体思路:
- 定义:两个头指针 ans 和 geX ,ans 存放小于 x 的结点,geX 存放大于等于 x 的结点;遍历指针 p 和 q ,分别用于遍历两个链表
- 遍历链表,将满足的结点连接到对应的链表后面,注意使用尾插法,因为要保持结点的相对次序;
- 主次:从主链表中,把大于等于 x 的结点拆出去,剩下的就是小于 x 的结点;
- 对等:把主链表中的小于 x 的结点拆到一条链表中,大于等于 x 的结点拆分到另一条链表中;
- 两种方法基本一样,就是写法不同;
- 连接两个链表;
- 返回结果;
四、参考代码
4.1 主次
时间复杂度: O ( n ) \Omicron(n) O(n)
空间复杂度: O ( 1 ) \Omicron(1) O(1)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* partition(ListNode* head, int x) {
ListNode *ans = new ListNode(0, head), *p = ans;
ListNode *geX = new ListNode(), *q = geX;
while (p != nullptr && p->next != nullptr) {
if (p->next->val >= x) {
q->next = p->next;
p->next = p->next->next;
q = q->next;
} else {
p = p->next;
}
}
q->next = nullptr;
p->next = geX->next;
return ans->next;
}
};
4.2 对等( LeetCode 官方给的版本)
时间复杂度: O ( n ) \Omicron(n) O(n)
空间复杂度: O ( 1 ) \Omicron(1) O(1)
class Solution {
public:
ListNode* partition(ListNode* head, int x) {
ListNode* small = new ListNode(0);
ListNode* smallHead = small;
ListNode* large = new ListNode(0);
ListNode* largeHead = large;
while (head != nullptr) {
if (head->val < x) {
small->next = head;
small = small->next;
} else {
large->next = head;
large = large->next;
}
head = head->next;
}
large->next = nullptr;
small->next = largeHead->next;
return smallHead->next;
}
};