86 Partition List
/**
* 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) {
//如果使用原链表调整
//保证一个head 一个more more指向最前面>=3的结点——>
//每读一个结点先判断x值:若大于等于 就不管 最开始的时候要将more指向这个结点;若小于则需要找more前面的结点 也就是less less作为小链表的尾指针 在less和more之间插入这个链表
if(!head)
return head;
ListNode* less = nullptr, *more = nullptr;
ListNode* ptr = head;
if(ptr->val < x){
less = ptr;
}else{
more = ptr;
}
while(ptr->next != nullptr){//处理的是ptr->next ptr作为前置结点帮助插入
int n = ptr->next->val;
if(n >= x){
//more的任务找到大节点的头部,所以只有在第一次找到大节点的时候more才会动
if(more == nullptr){
more = ptr->next;
}
}else{
//只有小的要往前插 找less 和 more
//less的任务找到小结点的尾部,所以每次找到小的先要确定是不是在小链表尾部
if(less->next == ptr->next){
less = less->next;
}else{//不在则需要插入 将ptr->next插入在less和more之间 需要ptr
ListNode* temp = ptr->next;//单独拎出来
ptr->next = ptr->next->next;
less->next = temp;
temp->next = more;
less = less->next;
}
}
ptr = ptr->next;
}
}
};
但是会发生断裂????【看下方分析】
正确:新建两个链表 挪动原链表结点到lessHead和moreHead中 最后再合并
/**
* 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) {
//如果使用原链表调整
//保证一个head 一个more more指向最前面>=3的结点——>
//每读一个结点先判断x值:若大于等于 就不管 最开始的时候要将more指向这个结点;若小于则需要找more前面的结点 也就是less less作为小链表的尾指针 在less和more之间插入这个链表
if(!head)
return head;
//虚拟头
ListNode* lessHead = new ListNode(0);
ListNode* moreHead = new ListNode(0);
ListNode* less = lessHead ,*more = moreHead;//指向尾部
ListNode* ptr = head;
while(ptr){
if(ptr->val < x){
less->next = ptr;//小于则加入less链表
less = less->next;
}else{
more->next = ptr;//大于等于则加入more链表
more = more->next;
}
ptr = ptr->next;
}
less->next = moreHead->next;//链接
more->next = nullptr;//防止形成环
return lessHead->next;
}
};
错误分析
原本思路是 使用 more 作为一个标记,指向第一个 >=x 的节点,而不去维护一个独立的链表,这样的做法 本质上是试图在原链表上完成调整,而不是创建两个链表再合并。这种方式理论上可行,但它在实现上会有一些 潜在的问题:
143. Reorder List
143. Reorder List
/**
* 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:
void reorderList(ListNode* head) {
//将链表重排——>0 n 1 n-1 2 n-2的顺序
//先将链表拆成两个 一个正向尾插 一个逆向头插
//然后将两个链表结点交叉放入新链表中
if(!head)
return ;
ListNode* list1 = new ListNode(0);//n+1/2个正 尾插
ListNode* list2 = new ListNode(0);//n/2个逆 头插
ListNode* ptr = head;
ListNode* tail1 = list1;
//首先知道链表结点数
while(ptr->next){
ptr = ptr->next;
}
int num = ptr->val;
ptr = head;//重置
while(ptr->val <= (num+1)/2){//尾插
tail1->next = ptr;
tail1 = tail1->next;
ptr = ptr->next;
}
tail1->next = nullptr;//记得封边
while(ptr){//头插
ListNode* temp = list2->next;
list2->next = ptr;
list2->next->next = temp;//记得封边
ptr = ptr->next;
}
//然后将两个链表交叉组合在一起就好
tail1 = list1;
ListNode* tail2 = list2;
ptr = head;
for(int i = 0 ; i < num ; i++){
if(i % 2 == 0){
//list1
ptr->next = tail1->next;
tail1 = tail1->next;
}else{
//list2
ptr->next = tail2->next;
tail2 = tail2->next;
}
ptr = ptr->next;
}
}
};
【属于是思路没问题 但是太菜!】
/**
* 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:
void reorderList(ListNode* head) {
//确定中点slow
ListNode* fast = head , *slow = head;
while(fast && fast->next){
slow = slow->next;
fast = fast->next->next;
}
//逆转后半部分
ListNode* prev = nullptr,*ptr = slow->next;
slow->next = nullptr;//断开前后部分
while(ptr){
ListNode* next = ptr->next;
ptr->next = prev;
prev = ptr;
ptr = next;
}
ListNode* list2 = prev;
ListNode* list1 = head;
//交叉合并两个链表
while(list1 && list2){
ListNode* temp1 = list1->next;
ListNode* temp2 = list2->next;
list1->next = list2;
if(temp1 == nullptr)break;
list2->next = temp1;
list1 = list1->next->next;
list2 = temp2;
}
}
};
148. Sort List
/**
* 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* sortList(ListNode* head) {
if(!head)
return head;
//对链表重新排序 时间复杂度要低 快速排序
//但是他没说一定是结点该位置 也可以是该数值
ListNode* ptr = head;
vector<int> num;
while(ptr){
num.push_back(ptr->val);
ptr = ptr->next;
}
//vector排序
sort(num.begin() , num.end());
ptr = head;
int i = 0;
while(ptr){
ptr->val = num[i];
i++;
ptr = ptr->next;
}
return head;
}
};
147. Insertion Sort List
/**
* 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* insertionSortList(ListNode* head) {
//使用插入排序 返回被排序链表的头部
//已排序列表 + 待排序元素
//判断待排序元素在 前方列表的位置并插入
//直到没有待排序元素
ListNode* unsorted = head->next;
ListNode* sorted = new ListNode(0); sorted->next = head; sorted->next->next = nullptr;//链表
while(unsorted){
//首先判断shao在前面sorted的位置:遍历sorted直到找到中间值比前面大比后面小
ListNode* prev = sorted->next;
while(prev && prev->next){
//比前面大比后面小
if(prev->val <= unsorted->val && prev->next->val > unsorted->val){
break;
}
prev = prev->next;
}
//最开始
ListNode* nex = unsorted->next;
if(prev->next == nullptr && prev->val > unsorted->val){//往前插入
sorted->next = unsorted;
unsorted->next = prev;
}else{
ListNode* temp = prev->next;//插入
prev->next = unsorted;
unsorted->next = temp;
}
//shao插入到sorted后 要更新shao
unsorted = nex;
}
return sorted->next;
}
};
/**
* 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* insertionSortList(ListNode* head) {
//使用插入排序 返回被排序链表的头部
//已排序列表 + 待排序元素
//判断待排序元素在 前方列表的位置并插入
//直到没有待排序元素
ListNode* unsorted = head->next;
ListNode* sorted = new ListNode(0); sorted->next = head; sorted->next->next = nullptr;//链表
while(unsorted){
//首先判断shao在前面sorted的位置:遍历sorted直到找到中间值比前面大比后面小
ListNode* prev = sorted->next;
while(prev->next && prev->next->val < unsorted->val){//保证prev->next 总<
prev = prev->next;
}
//最开始
ListNode* nex = unsorted->next;
if(prev->val > unsorted->val){//往前插入
unsorted->next = prev;
sorted->next = unsorted;
}else{
ListNode* temp = prev->next;//插入
unsorted->next = temp;
prev->next = unsorted;
}
//shao插入到sorted后 要更新shao
unsorted = nex;
}
return sorted->next;
}
};
下面的更简洁
class Solution {
public:
ListNode* insertionSortList(ListNode* head) {
if (!head || !head->next) return head; // 处理空链表或单节点情况
ListNode* sorted = new ListNode(0); // 哑结点,简化操作
ListNode* unsorted = head;
while (unsorted) {
ListNode* nextNode = unsorted->next; // 记录下一个待排序元素
ListNode* prev = sorted;
// **找到插入位置:prev->next 的值要比 unsorted 大**
while (prev->next && prev->next->val < unsorted->val) {
prev = prev->next;
}
// **插入 unsorted 到 sorted**
unsorted->next = prev->next;
prev->next = unsorted;
// **更新 unsorted,处理下一个元素**
unsorted = nextNode;
}
return sorted->next; // 返回去掉哑结点的头部
}
};