LeetCode 面试经典 150_链表_分隔链表(65_86_C++_中等)(拆分+尾插法)
LeetCode 面试经典 150_链表_分隔链表(65_86_C++_中等)
- 题目描述:
- 输入输出样例:
- 题解:
- 解题思路:
- 思路一(拆分+尾插法):
- 代码实现
- 代码实现(思路一(拆分+尾插法)):
- 以思路一为例进行调试
题目描述:
给你一个链表的头节点 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
题解:
解题思路:
思路一(拆分+尾插法):
1、对链表进行分隔,可以想到使用两个链表来进行拆分。 保留 两个分区中每个节点的初始相对位置,我们可以想到采用尾插法。
- 创建两个虚拟头节点:用来分别存储小于 x 的节点和大于等于 x 的节点。
- 将每个节点根据其值判断是放到小链表还是大链表。
- 将小链表和大链表连接起来,小链表的尾节点指向大链表的头节点。
2、复杂度分析:
① 时间复杂度:O(n),n 代表单链表中元素的个数,只遍历了一遍单链表。
② 空间复杂度:O(1),使用了常数个存储空间。
代码实现
代码实现(思路一(拆分+尾插法)):
class Solution {
public:ListNode* partition(ListNode* head, int x) {// 创建两个虚拟头节点,一个用于存储小于x的部分,另一个用于存储大于等于x的部分ListNode *dummyHead_Small = new ListNode(-1); // 用于存储小于x的节点ListNode *dummyHead_Big = new ListNode(-1); // 用于存储大于等于x的节点// 初始化两个尾指针,分别指向各自的虚拟头节点ListNode *Small_tail = dummyHead_Small;ListNode *Big_tail = dummyHead_Big;// 当前节点指针,遍历原链表ListNode *curNode = head;// 遍历整个链表,将小于x的节点添加到dummyHead_Small链表中,// 将大于等于x的节点添加到dummyHead_Big链表中while(curNode != nullptr) {if(curNode->val < x) {// 如果当前节点的值小于x,将其加入到small链表中Small_tail->next = curNode;Small_tail = Small_tail->next; // 更新small链表的尾节点} else {// 如果当前节点的值大于等于x,将其加入到big链表中Big_tail->next = curNode;Big_tail = Big_tail->next; // 更新big链表的尾节点}curNode = curNode->next; // 移动到下一个节点}// 将small链表的尾部连接到big链表的头部Small_tail->next = dummyHead_Big->next;// 断开big链表的尾部,防止环形链表Big_tail->next = nullptr;// 由于dummyHead_Small是一个虚拟头节点,返回其下一个节点作为新的headhead = dummyHead_Small->next;// 释放虚拟头节点的内存delete dummyHead_Big;delete dummyHead_Small;return head; // 返回重新排序后的链表头}
};
以思路一为例进行调试
#include<iostream>
#include<vector>
using namespace std;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) {}
};//尾插法创建链表
ListNode *createList(vector<int> nums){ListNode *head=nullptr,*tail=nullptr;for (auto &num : nums){if (head==nullptr){head=tail=new ListNode(num);}else{tail->next=new ListNode(num);tail=tail->next;}}return head;
} class Solution {
public:ListNode* partition(ListNode* head, int x) {// 创建两个虚拟头节点,一个用于存储小于x的部分,另一个用于存储大于等于x的部分ListNode *dummyHead_Small = new ListNode(-1); // 用于存储小于x的节点ListNode *dummyHead_Big = new ListNode(-1); // 用于存储大于等于x的节点// 初始化两个尾指针,分别指向各自的虚拟头节点ListNode *Small_tail = dummyHead_Small;ListNode *Big_tail = dummyHead_Big;// 当前节点指针,遍历原链表ListNode *curNode = head;// 遍历整个链表,将小于x的节点添加到dummyHead_Small链表中,// 将大于等于x的节点添加到dummyHead_Big链表中while(curNode != nullptr) {if(curNode->val < x) {// 如果当前节点的值小于x,将其加入到small链表中Small_tail->next = curNode;Small_tail = Small_tail->next; // 更新small链表的尾节点} else {// 如果当前节点的值大于等于x,将其加入到big链表中Big_tail->next = curNode;Big_tail = Big_tail->next; // 更新big链表的尾节点}curNode = curNode->next; // 移动到下一个节点}// 将small链表的尾部连接到big链表的头部Small_tail->next = dummyHead_Big->next;// 断开big链表的尾部,防止环形链表Big_tail->next = nullptr;// 由于dummyHead_Small是一个虚拟头节点,返回其下一个节点作为新的headhead = dummyHead_Small->next;// 释放虚拟头节点的内存delete dummyHead_Big;delete dummyHead_Small;return head; // 返回重新排序后的链表头}
};int main(int argc, char const *argv[])
{vector <int> num={1,4,3,2,5,2};int x=3;ListNode *head = createList(num);Solution s;ListNode *ans = s.partition(head,x);while (ans!=nullptr){cout<<ans->val<<" ";ans=ans->next;}return 0;
}
LeetCode 面试经典 150_链表_分隔链表(65_86)原题链接
欢迎大家和我沟通交流(✿◠‿◠)
