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

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

给你链表的头结点 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; // 返回排序后的链表
    }
};
相关文章
|
存储 C++
魔幻而精妙:探秘杨辉三角的奥秘
在这篇文章中,我们将深入研究题目 杨辉三角的内涵与解决方法。杨辉三角是数学领域的一颗璀璨明珠,通过对该问题的解析,笔者将揭示它独特的规律与生成方式。
134 0
|
9月前
|
算法
转变命运!揭秘反转链表的神奇算法!
转变命运!揭秘反转链表的神奇算法!
|
9月前
|
搜索推荐
手撕各种排序(中)
手撕各种排序(中)
78 0
|
9月前
|
算法 搜索推荐 索引
手撕各种排序(下)
手撕各种排序(下)
77 0
|
9月前
|
安全 Java C语言
手撕各种排序(上)
手撕各种排序
55 0
|
人工智能 搜索推荐 算法
【数据结构】手撕八大排序算法(上)
目录 1.排序的概念: 2.八大排序的思路及其细节 2.1直接插入排序
73 0
|
搜索推荐
【数据结构】手撕八大排序算法(下)
2.6快速排序: 快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,
86 0
|
算法 搜索推荐
【数据结构与算法篇】手撕八大排序算法之交换排序
【数据结构与算法篇】手撕八大排序算法之交换排序
119 0
|
机器学习/深度学习 存储 算法
【数据结构与算法篇】 手撕八大排序算法之选择排序
【数据结构与算法篇】 手撕八大排序算法之选择排序
71 0
|
算法 搜索推荐 Java
手撕八大排序(下)
手撕八大排序(下)
63 0