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

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

给你链表的头结点 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; // 返回排序后的链表
    }
};
相关文章
|
6月前
|
C语言
猿创征文|栈和队列OJ刷题
猿创征文|栈和队列OJ刷题
|
6月前
【一刷《剑指Offer》】面试题 16:反转链表
【一刷《剑指Offer》】面试题 16:反转链表
|
6月前
【一刷《剑指Offer》】面试题 6:重建二叉树
【一刷《剑指Offer》】面试题 6:重建二叉树
|
存储 C++ 容器
五道超经典题目,带你手撕链表题(多种方法实现)下
五道超经典题目,带你手撕链表题(多种方法实现)
61 1
|
6月前
|
算法
数据结构与算法之树
红黑树 1.如果一个树要是红黑树,那么这个树首先就要满足平衡二叉树的性质。
63 1
|
算法 搜索推荐
【数据结构与算法篇】手撕八大排序算法之交换排序
【数据结构与算法篇】手撕八大排序算法之交换排序
77 0
|
机器学习/深度学习 存储 算法
【数据结构与算法篇】 手撕八大排序算法之选择排序
【数据结构与算法篇】 手撕八大排序算法之选择排序
63 0
|
机器学习/深度学习 算法 Java
《八皇后问题》Java数据结构-JavaProject-JavaOJ题集
《八皇后问题》& Java数据结构 & JavaProject & JavaOJ题集
65 0
《八皇后问题》Java数据结构-JavaProject-JavaOJ题集
五道超经典题目,带你手撕链表题(多种方法实现)上
五道超经典题目,带你手撕链表题(多种方法实现)
110 0
|
算法 JavaScript 容器
牛客网《剑指offer》专栏刷题练习之数组专精
牛客网《剑指offer》专栏刷题练习之数组专精
90 0