排序链表---归并--链表OJ

https://leetcode.cn/problems/sort-list/submissions/499363940/?envType=study-plan-v2&envId=top-100-liked

这里我们直接进阶,用时间复杂度O(nlogn),空间复杂度O(1),来解决。

        对于归并,如果自上而下的话,空间复杂度为O(n),因为需要开辟n个结点

        所以我们要换种思路,自下而上,直接将链表看成独立的n个结点。

        首先合并算法:

struct ListNode* merge(struct ListNode* head1,struct ListNode* head2)
{
    struct ListNode* dummyHead = (struct ListNode*)malloc(sizeof(struct ListNode));
    dummyHead->val = 0,dummyHead->next = NULL;
    struct ListNode* tmp = dummyHead,*h1=head1,*h2=head2;
    while(h1 && h2)
    {
        if(h1->val <= h2->val)
        {
            tmp->next = h1;
            h1=h1->next;
        }
        else
        {
            tmp->next = h2;
            h2 = h2->next;
        }
        tmp = tmp->next;
    }
    if(h1)
    {
        tmp->next = h1;
    }
    if(h2)
    {
        tmp->next = h2;
    }
    return dummyHead->next;
}

        思路:

        这里的细节在于:找每组的子区间,找子区间的判断条件隔离子区间链接每一组,找下一组的子区间。

        具体代码如下:

struct ListNode* merge(struct ListNode* head1,struct ListNode* head2)
{
    struct ListNode* dummyHead = (struct ListNode*)malloc(sizeof(struct ListNode));
    dummyHead->val = 0,dummyHead->next = NULL;
    struct ListNode* tmp = dummyHead,*h1=head1,*h2=head2;
    while(h1 && h2)
    {
        if(h1->val <= h2->val)
        {
            tmp->next = h1;
            h1=h1->next;
        }
        else
        {
            tmp->next = h2;
            h2 = h2->next;
        }
        tmp = tmp->next;
    }
    if(h1)
    {
        tmp->next = h1;
    }
    if(h2)
    {
        tmp->next = h2;
    }
    return dummyHead->next;
}

struct ListNode* sortList(struct ListNode* head) {
    if(head == NULL)
        return head;
    int len = 0;//长度
    for(struct ListNode* cur = head;cur!=NULL;cur=cur->next)len++;
    
    struct ListNode* dummy = malloc(sizeof(struct ListNode));
    dummy->val = 0,dummy->next = head;

    //自底向上归并排序
    for(int sublen = 1;sublen < len;sublen*=2)
    {
        struct ListNode* pre = dummy,*cur=dummy->next;//每次从新的头开始记录
        while(cur)
        {
            struct ListNode* head1 = cur;//第一个头就是cur
            for(int i = 1;i<sublen && cur->next!=NULL;i++)//找1子区间的尾,并且2子区间不为空
            {
                cur = cur->next;
            }
            //如果for是在cur->next == NULL结束的,那2子区间头就是空
            struct ListNode* head2=cur->next;//2子区间的头
            cur->next = NULL;//将1子区间分离出来
            cur = head2;
            //再找2子区间的尾
            for(int i = 1;i<sublen && cur!=NULL;i++)
            {
                cur=cur->next;
            }

            struct ListNode* next = NULL;//记录下一组的头
            //如果cur为空,说明已经到了整个链表的最后
            if(cur != NULL)//cur不为空
            {
                next = cur->next;//记录下一组的头,可空可不空
                cur->next = NULL;//分离2子区间
            }
            struct ListNode* Merged = merge(head1,head2);//记录每次合并后的头
            pre->next = Merged;
            while(pre->next)//走到合并后的1,2区间的尾,pre来链接每一组
            {
                pre = pre->next;
            }
            cur = next;//进入下一组
        }
    }
    return dummy->next;
}

相关推荐

  1. 排序

    2024-01-31 22:32:01       28 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-01-31 22:32:01       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-01-31 22:32:01       100 阅读
  3. 在Django里面运行非项目文件

    2024-01-31 22:32:01       82 阅读
  4. Python语言-面向对象

    2024-01-31 22:32:01       91 阅读

热门阅读

  1. 使用Windows API实现屏幕截图及服务器传输

    2024-01-31 22:32:01       60 阅读
  2. SQL Server 函数参考手册

    2024-01-31 22:32:01       53 阅读
  3. Filebeat日志采集到Logstash再到Elasticsearch集群

    2024-01-31 22:32:01       64 阅读
  4. c++11学习笔记

    2024-01-31 22:32:01       71 阅读
  5. nginx+ gunicorn部署flask项目

    2024-01-31 22:32:01       47 阅读
  6. 20240130

    20240130

    2024-01-31 22:32:01      52 阅读
  7. 2024.1.20 用户画像标签开发,面向过程方法

    2024-01-31 22:32:01       52 阅读
  8. 基于Qt 音乐播放器mp3(进阶)

    2024-01-31 22:32:01       51 阅读