归并排序,时间复杂度nlogn

思路:
/*
   考点:
   1. 快慢指针;2. 归并排序。
   此题经典,需要消化吸收。
   复杂度分析:
              T(n)            拆分 n/2, 归并 n/2 ,一共是n/2 + n/2 = n
             /    \           以下依此类推:
           T(n/2) T(n/2)      一共是 n/2*2 = n
          /    \  /     \
         T(n/4) ...........   一共是 n/4*4 = n
 
        一共有logn层,故复杂度是 O(nlogn)
因为题目要求复杂度为O(nlogn),故可以考虑归并排序的思想。
归并排序的一般步骤为:
1)将待排序数组(链表)取中点并一分为二;
2)递归地对左半部分进行归并排序;
3)递归地对右半部分进行归并排序;
4)将两个半部分进行合并(merge),得到结果。
 
所以对应此题目,可以划分为三个小问题:
1)找到链表中点 (快慢指针思路,快指针一次走两步,慢指针一次走一步,快指针在链表末尾时,慢指针恰好在链表中点);
2)写出merge函数,即如何合并链表。 (见merge-two-sorted-lists 一题解析)
3)写出mergesort函数,实现上述步骤。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
class Solution {
public :
     ListNode* findMiddle(ListNode* head){
         ListNode* chaser = head;
         ListNode* runner = head->next;
         while (runner != NULL && runner->next != NULL){
             chaser = chaser->next;
             runner = runner->next->next;
         }
         return chaser;
     }
     
  ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
         if (l1 == NULL){
             return l2;
         }
         if (l2 == NULL){
             return l1;
         }
         ListNode* dummy =  new ListNode(0);
         ListNode* head = dummy;
         while (l1 != NULL && l2 != NULL){
             if (l1->val > l2->val){
                 head->next = l2;
                 l2 = l2->next;
             }
             else {
                 head->next = l1;
                 l1 = l1->next;
             }
             head = head->next;
         }
         if (l1 == NULL){
             head ->next = l2;
         }
         if (l2 == NULL){
             head->next = l1;
         }
         return dummy->next;
     }
     
     ListNode* sortList(ListNode* head) {
         if (head == NULL || head ->next == NULL){
             return head;
         }
         ListNode* middle = findMiddle(head);
         ListNode* right = sortList(middle->next);
         middle -> next = NULL;
         ListNode* left = sortList(head);
         return mergeTwoLists(left, right);
     }
};

 

转载于:https://www.cnblogs.com/serser/p/6514156.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值