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

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

给你链表的头结点 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; // 返回排序后的链表
    }
};
相关文章
|
1月前
|
算法 安全 NoSQL
2024重生之回溯数据结构与算法系列学习之顺序表习题精讲【无论是王道考研人还真爱粉都能包会的;不然别给我家鸽鸽丢脸好嘛?】
顺序表的定义和基本操作之插入;删除;按值查找;按位查找习题精讲等具体详解步骤以及举例说明
|
2月前
|
存储 搜索推荐 算法
手撕十大排序算法
手撕十大排序算法
|
7月前
|
搜索推荐
手撕各种排序(中)
手撕各种排序(中)
72 0
|
7月前
|
算法 搜索推荐 索引
手撕各种排序(下)
手撕各种排序(下)
66 0
|
7月前
|
安全 Java C语言
手撕各种排序(上)
手撕各种排序
51 0
|
搜索推荐 算法 Java
快速排序算法,这么写打败95%的程序员
1960年,英国计算机科学家霍尔提出了一种高效的排序算法——快速排序。其核心思想是选定一个基准元素,将需排序的数组分割成两部分。其中一部分都比基准元素小,另一部分都比基准元素大。接着对这两部分分别进行快速排序,最后通过递归完成整个排序过程。这种算法效率高,被广泛应用。
|
算法 搜索推荐
【数据结构与算法篇】手撕八大排序算法之交换排序
【数据结构与算法篇】手撕八大排序算法之交换排序
106 0
|
机器学习/深度学习 存储 算法
【数据结构与算法篇】 手撕八大排序算法之选择排序
【数据结构与算法篇】 手撕八大排序算法之选择排序
68 0
|
算法 搜索推荐 Java
手撕八大排序(下)
手撕八大排序(下)
55 0
|
搜索推荐
手撕八大排序(上)
手撕八大排序(上)
119 0
手撕八大排序(上)