链表分割

举报
芒果_Mango 发表于 2022/04/30 22:53:48 2022/04/30
【摘要】 大家好,我是芒果,一名非科班的在校大学生。对C/C++、数据结构、Linux及MySql、算法等领域感兴趣,喜欢将所学知识写成博客记录下来。 希望该文章对你有所帮助!如果有错误请大佬们指正!共同学习交流作者简介:CSDN C/C++领域新星创作者https://blog.csdn.net/chuxinchangcun?type=blog掘金LV3用户 https://juejin.cn/us...

大家好,我是芒果,一名非科班的在校大学生。对C/C++、数据结构、Linux及MySql、算法等领域感兴趣,喜欢将所学知识写成博客记录下来。 希望该文章对你有所帮助!如果有错误请大佬们指正!共同学习交流

作者简介:


题目要求

链接:链表分割牛客题霸牛客网 (nowcoder.com)

描述

现有一链表的头指针 ListNode* pHead,给一定值x,编写一段代码将所有小于x的结点排在其余结点之前,且不能改变原来的数据顺序,返回重新排列后的链表的头指针。


image-20220210163022752

即:把结点的值小于x的放在左边,大于x的放在右边。相对顺序不可以改变


如果是不需要考虑相对顺序,左边存比x小的结点,右边存大于等于x的结点

思路:

  • 创建一个新链表,定义头尾指针,方便头插和尾插
  • 定义指针cur,用于遍历原链表
  • 如果cur指向的值比x小:头插到新链表 ->更新头指针 否则尾插到新链表 ->更新尾指针

思路

  • 创建两个带哨兵位的链表

  • 一个用于存放值小于x的结点,记为lessHead,一个用于存放值大于等于x的结点,记为greaterHead

  • 为了方便插入,两个链表分别定义头尾指针,用于标志头和尾。最初都指向哨兵位

  • 定义一个指针cur用于遍历原来的链表

    • 如果cur指向的值小于x:尾插到lesstail的后面,然后更新lesstail的位置
    • 否则:尾插到greatertail的后面,然后更新greatertail的位置
    • 循环结束条件:把原链表的结点都遍历完成。即cur为空
  • 由于值小于x的放在链表前面,所以最后:把lesstail->next链接greaterHead->next(greaterHead链表的第一个结点)

    注意点:

    1:lessHead和greaterHead为哨兵位,二者的next才是第一个结点

    2.要防止形成环(原链表的尾的前一个结点比x大,尾结点比x小,链接之后,会形成环),所以要将greatertail->next置空

    image-20220210163038733

    3.要释放动态开辟的两个哨兵位,防止内存泄露。

    • 要先保存lessHead->next结点的位置记为newhead,不然释放之后就找不到了
    • 以newhead为头的链表就是比x小的在左边,比x大的在右边
    • 最后返回newhead即可

图解

image-20220210163112472


image-20220210163123613


链接时候:原链表的真实变化

例子:原链表为 5 -> 3 -> 6 -> 2 -> NULL

image-20220210163204740


代码:

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class Partition {
public:
    ListNode* partition(ListNode* pHead, int x) {
        // write code here
        //链表为空,直接返回
        if(pHead == NULL)
        {
            return NULL;
        }
        //开辟两个链表 (使用哨兵位结点)
        struct ListNode*lessHead = (struct ListNode*)malloc(sizeof(struct ListNode));
        struct ListNode*greaterHead = (struct ListNode*)malloc(sizeof(struct ListNode));
        //为了方便尾插,再定义一个尾指针
        struct ListNode* lesstail = lessHead;
        struct ListNode* greatertail = greaterHead;
        
        //比x小的尾插到lessHead 大于等于x的尾插到greaterHead链表
        //cur用于遍历原链表
        struct ListNode* cur = pHead;
        while(cur)
        {
            //结点的值比x小,就链接到less的后面
            if(cur->val < x)
            {
                //链接cur
                lesstail ->next =cur;
                //更新less的尾结点
                lesstail = cur;
            }
            //结点的值大于等于x,就链接到greater的后面
            else
            {
                //链接cur
                greatertail -> next = cur;
                //更新greater的尾结点
                greatertail = cur;
            }
            //cur指向原链表的下一个结点
            cur = cur->next;
        }
        //链接两个链表
        //排成升序,所以是greater的第一个结点链接到less的尾
        lesstail->next = greaterHead -> next;//greater是哨兵位,greaterHead的next才是第一个结点
        //为了防止成环,要把greater的尾置空
        greatertail ->next = NULL;
        
        //防止内存泄露,要释放两个哨兵位结点
        //要先保存新链表的头
        struct ListNode* newhead = lessHead->next;//less的下一个结点才是头,less是哨兵位
        //释放两个哨兵位
        free(lessHead);
        free(greaterHead);
        return newhead;
    }
};

\

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。