思路:
/*
  考点:
  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);
    }
};

 

归并排序,时间复杂度nlogn的更多相关文章

  1. 快速排序的时间复杂度nlogn是如何推导的??

    本文以快速排序为例,推导了快排的时间复杂度nlogn是如何得来的,其它算法与其类似. 对数据Data = { x1, x2... xn }: T(n)是QuickSort(n)消耗的时间: P(n)是 ...

  2. 归并排序O(nlogn)

    先分治再合并 代码 #include<bits/stdc++.h> using namespace std; #define ll long long int a[1000],t[1000 ...

  3. 平均时间复杂度为O(nlogn)的排序算法

    本文包括 1.快速排序 2.归并排序 3.堆排序 1.快速排序 快速排序的基本思想是:采取分而治之的思想,把大的拆分为小的,每一趟排序,把比选定值小的数字放在它的左边,比它大的值放在右边:重复以上步骤 ...

  4. 快排的时间复杂度O(n) = nlogn计算过程

    转载:https://www.cnblogs.com/javawebsoa/p/3194015.html 本文以快速排序为例,推导了快排的时间复杂度nlogn是如何得来的,其它算法与其类似. 对数据D ...

  5. java泛型中使用的排序算法——归并排序及分析

    一.引言 我们知道,java中泛型排序使用归并排序或TimSort.归并排序以O(NlogN)最坏时间运行,下面我们分析归并排序过程及分析证明时间复杂度:也会简述为什么java选择归并排序作为泛型的排 ...

  6. 快速排序 O(n logn) 堆排序 O(n logn) 归并排序 O(n logn)

    NB三人组 快速排序 思路" 取一个元素P (第一个元素), 使元素归位 列表被P 分成两部分,左边都比P小,右边比P大; 递归完成排序. 问题 如果是已经排序好的 倒叙 列表 则会 递归深 ...

  7. 快速排序 Vs. 归并排序 Vs. 堆排序——谁才是最强的排序算法

    知乎上有一个问题是这样的: 堆排序是渐进最优的比较排序算法,达到了O(nlgn)这一下界,而快排有一定的可能性会产生最坏划分,时间复杂度可能为O(n^2),那为什么快排在实际使用中通常优于堆排序? 昨 ...

  8. 归并排序(归并排序求逆序对数)--16--归并排序--Leetcode面试题51.数组中的逆序对

    面试题51. 数组中的逆序对 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数. 示例 1: 输入: [7,5,6,4] 输出 ...

  9. 处理海量数据的高级排序之——归并排序(C++)

    代码实现                                                                                                 ...

随机推荐

  1. retain, copy, assign以及autorelease

    一,retain, copy, assign区别 1. 假设你用malloc分配了一块内存,并且把它的地址赋值给了指针a,后来你希望指针b也共享这块内存,于是你又把a赋值给(assign)了b.此时a ...

  2. AutoLayout处理UITableView动态高度

    我们经常会遇到UITableViewCell的高度要跟随内容而调整,在未引入AutoLayout之前,我们使用以下方法计算Label高度,然后heightForRowAtIndexPath中返回计算的 ...

  3. C语言结构体和共用体_07

    概述 定义结构体类型变量的方法 结构体变量的引用 结构体变量的初始化 结构体数组 指向结构体类型数据的指针 用指针处理链表 共用体 枚举类型 用 typedef定义类型  概述 定义一个结构体的一般形 ...

  4. CF-1013 (2019/02/09 补)

    CF-1013 A. Piles With Stones 比较两个序列的和,因为只能拿走或者不拿,所以总数不能变大. B. And 答案只有 -1,0,1,2几种可能,所以对于每一种答案都暴力扫一次是 ...

  5. 自然数的拆分(DFS)

    题目描述: 任何一个大于1的自然数n,总可以拆分成若干个小于n的自然数之和. 输入格式: 待拆分的自然数n. 输出格式: 若干数的加法式子. 样例输入: 7 样例输出: 1+1+1+1+1+1+1 1 ...

  6. PAT 乙级 1045

    题目 题目地址:PAT 乙级 1045 题解 本题的解法比较巧妙,刚开始的试着用暴力求解,果不其然时间超限…… 变换思路,既然对于每个元素来说满足的条件是前小后大,那么对数组排序,对应的位置相等的即为 ...

  7. 【点分治】luoguP2664 树上游戏

    应该是一道中等难度的点分?麻烦在一些细节. 题目描述 lrb有一棵树,树的每个节点有个颜色.给一个长度为n的颜色序列,定义s(i,j) 为i 到j 的颜色数量.以及 现在他想让你求出所有的sum[i] ...

  8. mysql中的的按小数位截取

    format()函数返回类型是字符串,满三位会加一个逗号. 针对数字类型转换建议使用 convert或者cast函数,用法如下: format(param, 2) (不建议) convert(para ...

  9. .Net Core依赖注入中TryAddEnumerable 和TryAddTransient方法的区别

    .Net Core依赖注入添加的每个服务,最终都会转换为一个ServiceDescriptor的实例,ServiceDescriptor包含以下属性: Lifetime:服务的生命周期(Singlet ...

  10. mysql的字符串连接符

    以前用SQL Server 连接字符串是用“+”,现在数据库用mysql,写个累加两个字段值SQL语句居然不支持"+",郁闷了半天在网上查下,才知道mysql里的+是数字相加的操作 ...