LeetCode 148. 排序链表 基于快速排序

148. 排序链表 - 力扣(LeetCode) (leetcode-cn.com)

  • 看好多题解都是基于归并排序的。确实链表用归并排序比较适合。且这道题单纯用快速排序在特殊数据超时了,因为链表不支持随机访问,所以不能随机选取主元,导致特殊情况时间复杂度很大。
  • 笔者主要利用这道题复习快速排序和递归思想
    请添加图片描述
  • 思路基于快速就排序分治思想。创建头结点指向根节点,用根节点作为主元pivot,把比主元小的抽出来插入到主元左边(注意是插入到dummyHead随即后面的下一个(每次都如此)),大的在主元右边不用调整。全部分离后在令pivot的next为NULL(为什么要为NULL?因为链表的结束判断为NULL。没有NULL将无法停止,也就是我们先断开,后面再拼接起来),记得先保存pivot->next哦。然后就分成两段了,分成2个继续递归下去即可。那么怎么重新连接起来呢?先看下面的代码
//类似北航算法课的快排法
//但是由于链表不支持随机访问,所以不能随机选取主元,导致特殊情况时间复杂度很大。leetcode超时了,但是对的
class Solution {
public:
    ListNode* sortList(ListNode* head) {
        if (head == NULL || head->next == NULL) return head;
        ListNode* dummyHead = new ListNode;
        ListNode* pivot = dummyHead->next = head;
        ListNode* curPre = head;
        ListNode* cur = head->next;
        ListNode* tmp1, *tmp2;
        while (cur != NULL) {
        	//如果比pivot小就挪到dummyHead的后一个,注意是随即的后一个哦
            if (cur->val < pivot->val) {
                tmp1 = dummyHead->next;
                tmp2 = cur->next;
                dummyHead->next = cur;
                cur->next = tmp1;
                cur = curPre->next = tmp2;
            }
            else {
                curPre = cur;
                cur = cur->next;
            }
        }
        ListNode* head2 = pivot->next;
        pivot->next = NULL;//先断尾
        //这里是理解递归的关键,每次都先走这里,那么其实是每次递归都先将左边的断开后排序排序
        dummyHead->next = sortList(dummyHead->next);
        //拼接起来,因为pivot是不会变的,在前面链表的末尾位置不变,即我们让前面链表pivot之前指向空的重新指向一个新排序好的根节点
        pivot->next = sortList(head2);
        return dummyHead->next;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值