LeetCode:148. Sort List

一、问题描述

Sort a linked list in O(n log n) time using constant space complexity.

Example 1:

Input: 4->2->1->3
Output: 1->2->3->4

Example 2:

Input: -1->5->3->4->0
Output: -1->0->3->4->5

二、解题思路

单链表排序,其实就是将链表分割、然后合并。本质上还是Merge Two Sorted Lists,只不过之前由加上了归并。

即:首先将链表分割成两部分,然后对这两部分进行排序。

链表数据的排序,时间复杂度控制在O(n log n)以内;空间复杂度为常数,即O(1),不允许使用额外的空间。
首先是链表排序,不能像数组一样随意的访问元素。归并排序,时间复杂度为O(n log n),满足要求。空间复杂度,数组下的归并排序为O(n),即建立一个数组来存放排好的数。但在链表数据结构下,空间复杂度为O(1)。因为链表的节点从一开始给定后就不在变更,在排序过程中只是每个节点指向位置不同,即指针变化,而节点数不变。
归并排序的核心思想就是:将原数组分开并递归此步骤,直到只有1个数时,开始比较排序并合并,即归并。在链表中也类似,从head节点往后移动,找到中间节点并把链表一分为二,递归此步骤。

具体是:设置快速指针fast和慢速指针slow,fast跑两步slow跑一步,当fast跑的最后一个节点时,slow到达middle处。递归上述步骤,归并时将节点重新排列。

注:链表,无new ListNode()代码便不生成新节点,没有额外空间。当使用ListNode* p创建新的链表指针时,并没有建立新节点没有增加额外空间,只是为了改变已有节点的指向(空间复杂度为O(1))。

三、代码实现

/**
 * 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 || !head->next) return head;
       
        ListNode *slow = head, *fast = head, *pre = head;
        while (fast && fast->next)
        {
            pre = slow;
            slow = slow->next;
            fast = fast->next->next;
        }//退出循环时,fast或fast->next = nullptr,slow指向中部位置
        pre->next = NULL; //将左右子链表断开处
        return mergeTwoLists(sortList(head), sortList(slow)); //归并左右子链表     
    }
private:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        if(l1 == NULL && l2 == NULL) return NULL;
        else if(l1 != NULL && l2 == NULL) return l1;
        else if(l1 == NULL && l2 != NULL) return l2;
        else {
            ListNode* preHead = new ListNode(0);
            //preHead 需要移动,因此使用resultHead来先保存下
            ListNode* resultHead = preHead;
            while( l1!=NULL && l2!=NULL){
                //同时不为空,那就比较。然后将小的添加到preHead的尾部
                if(l1->val < l2->val){
                    preHead->next = l1;
                    preHead = preHead->next;
                    l1 = l1->next;
                }else{
                    preHead->next = l2;
                    preHead = preHead->next;
                    l2 = l2->next;
                }
                //while结束,说明有一个为空了,那就把不为空的直接加上
                if(l1!=NULL) preHead->next = l1;
                if(l2!=NULL) preHead->next = l2;
            }
            return resultHead->next;
        }
    }
};

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章