zoukankan      html  css  js  c++  java
  • 代码题(33)— 排序链表、对链表进行插入排序

    1、148. 排序链表

    在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。

    示例 1:

    输入: 4->2->1->3
    输出: 1->2->3->4
    

    示例 2:

    输入: -1->5->3->4->0
    输出: -1->0->3->4->5

      常见排序方法有很多,插入排序,选择排序,堆排序,快速排序,冒泡排序,归并排序,桶排序等等。。它们的时间复杂度不尽相同,而这里题目限定了时间必须为O(nlgn),符合要求只有快速排序,归并排序,堆排序,而根据单链表的特点,最适于用归并排序。

    方法一:归并用的递归

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode* sortList(ListNode* head) {
            if(head == nullptr || head->next == nullptr)
                return head;
            ListNode *pre = head, *mid = head, *fast = head;
            while(fast && fast->next)
            {
                pre = mid;
                mid = mid->next;
                fast = fast->next->next;
            }
            pre->next = nullptr;
            ListNode* res = merge(sortList(head), sortList(mid));
            return res;
        }
        
        ListNode* merge(ListNode* l1, ListNode* l2)
        {
            if(l1 == nullptr)
                return l2;
            if(l2 == nullptr)
                return l1;
            ListNode* cur = nullptr;
            if(l1->val <= l2->val)
            {
                cur = l1;
                cur->next = merge(l1->next, l2);
            }
            else
            {
                cur = l2;
                cur->next = merge(l1,l2->next);
            }
            return cur;
        }
    };

    方法二:归并用的循环方法

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode* sortList(ListNode* head) {
            if(head == nullptr || head->next == nullptr)
                return head;
            ListNode *pre = head, *mid = head, *fast = head;
            while(fast && fast->next)
            {
                pre = mid;
                mid = mid->next;
                fast = fast->next->next;
            }
            pre->next = nullptr;
            ListNode* res = merge(sortList(head), sortList(mid));
            return res;
        }
        
        ListNode* merge(ListNode* l1, ListNode* l2)
        {
            ListNode* dummy = new ListNode(-1);
            ListNode* cur = dummy;
            while(l1 && l2)
            {
                if(l1->val <= l2->val)
                {
                    cur->next = l1;
                    l1 = l1->next;
                }
                else
                {
                    cur->next = l2;
                    l2 = l2->next;
                }
                cur = cur->next;
            }
            if(l1)
                cur->next = l1;
            if(l2)
                cur->next = l2;
            return dummy->next;
        }
    };

    2、147. 对链表进行插入排序

    对链表进行插入排序。

    插入排序的动画演示如上。从第一个元素开始,该链表可以被认为已经部分排序(用黑色表示)。
    每次迭代时,从输入数据中移除一个元素(用红色表示),并原地将其插入到已排好序的链表中。

    插入排序算法:

    1. 插入排序是迭代的,每次只移动一个元素,直到所有元素可以形成一个有序的输出列表。
    2. 每次迭代中,插入排序只从输入数据中移除一个待排序的元素,找到它在序列中适当的位置,并将其插入。
    3. 重复直到所有输入数据插入完为止。

    示例 1:

    输入: 4->2->1->3
    输出: 1->2->3->4
    

    示例 2:

    输入: -1->5->3->4->0
    输出: -1->0->3->4->5
    

       链表的插入排序实现原理很简单,就是一个元素一个元素的从原链表中取出来,然后按顺序插入到新链表中,时间复杂度为O(n2),是一种效率并不是很高的算法,但是空间复杂度为O(1),以高时间复杂度换取了低空间复杂度。

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode* insertionSortList(ListNode* head) {
            ListNode* dummy = new ListNode(-1);
            ListNode* cur = dummy;
            ListNode* temp = head;
            while(head)
            {
                temp = head->next;
                cur = dummy;//一个个数比较,找到最后一个小于当前节点的位置
                while(cur->next != nullptr && cur->next->val <= head->val)
                    cur = cur->next;
                
                ListNode* t = cur->next;//链表中插入一个节点的操作
                cur->next = head;
                head->next = t;
                
                head = temp;
            }
            return dummy->next;
        }
    };
  • 相关阅读:
    java核心学习(八) 枚举类
    java核心学习(七) 内部类、匿名内部类、Lambda表达式
    算法-快速排序
    java核心学习(六) 面向接口编程
    java核心学习(五) 修饰符(重点是static、final)
    java 核心学习笔记(四) 单例类
    贪心 zoj3197
    贪心 poj3045
    三分 POJ3737
    浮点数二分答案 HDU1969
  • 原文地址:https://www.cnblogs.com/eilearn/p/9418812.html
Copyright © 2011-2022 走看看