链表排序?看完你也能手撕

简介: 链表排序?看完你也能手撕

给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表

示例 1:

输入:head = [4,2,1,3]

输出:[1,2,3,4]


示例 2:

输入:head = [-1,5,3,4,0]

输出:[-1,0,3,4,5]

先贴上我的通过页面,用时和内存都算前列,超过93.12%,不可思议,因为我的思路很简单,代码也就几行。

再看官方的代码和时空大小,代码特别长,非常容易写错,而且性能表现平平无奇。

leetcode官方ac代码:

//自顶向下归并
class Solution {
public:
    ListNode* sortList(ListNode* head) {
        return sortList(head, nullptr);
    }
 
    ListNode* sortList(ListNode* head, ListNode* tail) {
        if (head == nullptr) {
            return head;
        }
        if (head->next == tail) {
            head->next = nullptr;
            return head;
        }
        ListNode* slow = head, *fast = head;
        while (fast != tail) {
            slow = slow->next;
            fast = fast->next;
            if (fast != tail) {
                fast = fast->next;
            }
        }
        ListNode* mid = slow;
        return merge(sortList(head, mid), sortList(mid, tail));
    }
 
    ListNode* merge(ListNode* head1, ListNode* head2) {
        ListNode* dummyHead = new ListNode(0);
        ListNode* temp = dummyHead, *temp1 = head1, *temp2 = head2;
        while (temp1 != nullptr && temp2 != nullptr) {
            if (temp1->val <= temp2->val) {
                temp->next = temp1;
                temp1 = temp1->next;
            } else {
                temp->next = temp2;
                temp2 = temp2->next;
            }
            temp = temp->next;
        }
        if (temp1 != nullptr) {
            temp->next = temp1;
        } else if (temp2 != nullptr) {
            temp->next = temp2;
        }
        return dummyHead->next;
    }
};
 
//自底向上归并
class Solution {
public:
    ListNode* sortList(ListNode* head) {
        if (head == nullptr) {
            return head;
        }
        int length = 0;
        ListNode* node = head;
        while (node != nullptr) {
            length++;
            node = node->next;
        }
        ListNode* dummyHead = new ListNode(0, head);
        for (int subLength = 1; subLength < length; subLength <<= 1) {
            ListNode* prev = dummyHead, *curr = dummyHead->next;
            while (curr != nullptr) {
                ListNode* head1 = curr;
                for (int i = 1; i < subLength && curr->next != nullptr; i++) {
                    curr = curr->next;
                }
                ListNode* head2 = curr->next;
                curr->next = nullptr;
                curr = head2;
                for (int i = 1; i < subLength && curr != nullptr && curr->next != nullptr; i++) {
                    curr = curr->next;
                }
                ListNode* next = nullptr;
                if (curr != nullptr) {
                    next = curr->next;
                    curr->next = nullptr;
                }
                ListNode* merged = merge(head1, head2);
                prev->next = merged;
                while (prev->next != nullptr) {
                    prev = prev->next;
                }
                curr = next;
            }
        }
        return dummyHead->next;
    }
 
    ListNode* merge(ListNode* head1, ListNode* head2) {
        ListNode* dummyHead = new ListNode(0);
        ListNode* temp = dummyHead, *temp1 = head1, *temp2 = head2;
        while (temp1 != nullptr && temp2 != nullptr) {
            if (temp1->val <= temp2->val) {
                temp->next = temp1;
                temp1 = temp1->next;
            } else {
                temp->next = temp2;
                temp2 = temp2->next;
            }
            temp = temp->next;
        }
        if (temp1 != nullptr) {
            temp->next = temp1;
        } else if (temp2 != nullptr) {
            temp->next = temp2;
        }
        return dummyHead->next;
    }
};

       我的思路:正常排序大家都会写,链表排序呢,正是因为他没有随机读取的原因,两层遍历用时很久。那我们把他转换成数组,排序完,再转回来不就行了么?(这个方法当然也有局限性,但是能够投机取巧的还是可以的)

       ac代码(详细注释)

 

class Solution {
public:
    ListNode* sortList(ListNode* head) {
        ListNode *cur = head; // 创建一个指针cur并初始化为头节点
        vector<int> s; // 创建一个vector s,用于存储链表节点的值
        
        // 将链表节点的值存储到vector s中
        while(cur != nullptr) {
            s.push_back(cur->val);
            cur = cur->next; // 移动cur指针到下一个节点
        }
 
        cur = head; // 将cur重新指向头节点,用于重新排列链表节点的值
 
        // 对vector s中的值进行排序
        sort(s.begin(), s.end());
 
        // 将排序后的值重新赋给链表节点
        for(int i = 0; i < s.size(); i++) {
            cur->val = s[i];
            cur = cur->next; // 移动cur指针到下一个节点
        }
        
        return head; // 返回排序后的链表
    }
};
目录
打赏
0
0
0
0
25
分享
相关文章
|
8月前
|
算法竞赛偷分技巧
算法竞赛偷分技巧
40 3
魔幻而精妙:探秘杨辉三角的奥秘
在这篇文章中,我们将深入研究题目 杨辉三角的内涵与解决方法。杨辉三角是数学领域的一颗璀璨明珠,通过对该问题的解析,笔者将揭示它独特的规律与生成方式。
133 0
快速排序算法,这么写打败95%的程序员
1960年,英国计算机科学家霍尔提出了一种高效的排序算法——快速排序。其核心思想是选定一个基准元素,将需排序的数组分割成两部分。其中一部分都比基准元素小,另一部分都比基准元素大。接着对这两部分分别进行快速排序,最后通过递归完成整个排序过程。这种算法效率高,被广泛应用。
【数据结构与算法篇】手撕八大排序算法之交换排序
【数据结构与算法篇】手撕八大排序算法之交换排序
115 0
【数据结构与算法篇】 手撕八大排序算法之选择排序
【数据结构与算法篇】 手撕八大排序算法之选择排序
70 0
数据结构与算法 #18 下跳棋,极富想象力的同向双指针模拟
这道题是 LeetCode 上的 [1040. 移动石子直到连续 II](https://leetcode.cn/problems/moving-stones-until-consecutive-ii/),难度是 Meduium,难度分是 2455。虽然是 Medium 题,但是打 Hard 标签一点也不为过。长期作为中等题的难度 Top1,直到去年被 [2289. 使数组按非递减顺序排列 ](https://leetcode.cn/problems/steps-to-make-array-non-decreasing/) 题挤下来。
97 0
数据结构与算法 #18 下跳棋,极富想象力的同向双指针模拟
数据结构与算法之美 | 别怕,有我!KMP 算法详解
为什么我认为 KMP 算法就是个动态规划问题呢,等会再解释。对于动态规划,之前多次强调了要明确 dp 数组的含义,而且同一个问题可能有不止一种定义 dp 数组含义的方法,不同的定义会有不同的解法。
数据结构与算法之美 | 别怕,有我!KMP 算法详解
数据结构与算法——栈和队列<也不过如此>
📖作者介绍:22级树莓人(计算机专业),热爱编程<目前在c++阶段,因为最近参加新星计划算法赛道(白佬),所以加快了脚步,果然急迫感会增加动力>——目标Windows,MySQL,Qt,数据结构与算法,Linux,多线程,会持续分享学习成果和小项目的 📖作者主页:king&南星 📖专栏链接:数据结构 🎉欢迎各位→点赞👏 + 收藏💞 + 留言🔔​ 💬总结:希望你看完之后,能对你有所帮助,不足请指正!共同学习交流 🐾 ———————————————— 版权声明:本文为CSDN博主「热爱编程的小K」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等