2.26 链表中等 86 143 链表逆转 快慢指针找中点 交叉合并链表 148 147插入排序

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;
        }        
    }
};

在这里插入图片描述
在这里插入图片描述

 j
【属于是思路没问题 但是太菜!】

/**
 * 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; // 返回去掉哑结点的头部
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值