[C++]LeetCode: 125 Sort List (归并排序链表)

来源:互联网 发布:天猫淘宝京东哪个好 编辑:程序博客网 时间:2024/06/02 08:33

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

思路:题目要求我们使用常数空间复杂度,时间复杂度为O(nlog(n)). 满足这个时间复杂度的有快速排序,归并排序,堆排序。插入排序时间复杂度为O(n^2). 双向链表用快排比较合适,堆排序也可用于链表,单项链表适合于归并排序。我们就用归并排序的思想来完成链表的排序。

首先是用快慢双指针找到链表中间的位置,然后分成前后端分别递归的归并排序,最后合并。

这道题的归并排序思想,我们在Merge Two Sorted Lists中已经做过。我们需要每次找到中点,然后对左右进行递归,最后用Merge Two Sorted Lists把他们合并起来。

Attention:

1. 快慢指针找中间节点的方法,是常用方法,要熟练使用。

//将链表分成前后两部分 双指针找到中间节点        ListNode* fast = head;        ListNode* slow = head;        while(fast->next != NULL && fast->next->next != NULL)        {            slow = slow->next;            fast = fast->next->next;        }
2. 链表的数据结构是如何实现归并的方法的。定义一个合并后的链表,然后把合适的节点放进去。思想和数组是一样的,只是链表操作不一样。

复杂度:如果这里我们考虑递归的栈空间的话,空间复杂度是O(lg(n))

AC Code:

/** * 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 == NULL || head->next == NULL) return head;        //将链表分成前后两部分 双指针找到中间节点        ListNode* fast = head;        ListNode* slow = head;        while(fast->next != NULL && fast->next->next != NULL)        {            slow = slow->next;            fast = fast->next->next;        }        ListNode* head2 = slow->next;        slow->next = NULL;        ListNode* head1 = head;        head1 = sortList(head1);   //前半段归并排序        head2 = sortList(head2);   //后半段归并排序        return merge(head1, head2);    }private:    ListNode* merge(ListNode* h1, ListNode* h2)    {        ListNode* dummyhead = new ListNode(0);        ListNode* mlist = dummyhead;                while(h1 != NULL && h2 != NULL)        {            if(h1->val <= h2->val)            {                mlist->next = h1;                h1 = h1->next;            }            else            {                mlist->next = h2;                h2 = h2->next;            }            mlist = mlist->next;        }        if(h1 != NULL)        {            mlist->next = h1;        }        if(h2 != NULL)        {            mlist->next = h2;        }        return dummyhead->next;    }};

我们也可以不使用递归的方法,自底向上的非递归版本的归并排序,空间复杂度就是常数了。可以看下这篇博文:sort list.
排序是面试中很常见和基础的一个主题,我们需要对各种常见的排序算法要熟悉。尤其是算法的原理,很多题目虽然没有直接考察排序的实现,但是会用到其中的思想,比如经典的topK问题,用到了快排的原理。这篇文章中有提到,可以看看:Median of Two Sorted Arrays.所以我们应该要更加注重排序算法的原理。

0 0
原创粉丝点击