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

对一个单链表进行排序,要求时间复杂度为O(n log n),空间复杂度为常量

分析:在排序中高速排序,堆排序,归并排序等都是能够在O(n log n)的时间复杂度之内完毕的。

a)      高速排序能够进行空间复杂度为1的原地排序,但必须是在能够反向索引的情况下。比如通过下标的减法向前索引。或者通过双向指针进行索引(双向链表)。

b)      堆排序必需要大小为n的额外空间,不考虑。

c)       归并排序理论上也是须要n的额外空间的(合并的时候),可是考虑到此次是链表的特殊情况。能够借助链表的插入这样的方式进行破坏性的操作来达到排序的目的。即不改变每一个节点中的元素,每次到合并的时候就通过改动next指针又一次组成一条新的链表。终于达到常量空间O(n log n)时间的单链表排序,详细细节见代码。

代码例如以下:

在leetcode中提交时。仅仅需拷贝class中的函数就可以,此处完整的cpp文件是为了更好的模拟运行过程

#include<iostream>
using namespace std; //Sort a linked list in O(n log n) time using constant space complexity.
//尝试使用归并排序,待排序元素为单链表
struct ListNode {
int val;
ListNode *next;
}; class Solution {
public:
ListNode *sortList(ListNode *head)
{
ListNode * retHead = NULL;
int listLen = GetLen(head);
if (listLen < 2)
{
return head;
}
retHead = MergeSort(head,listLen);
return retHead; } //获取距离head长度为len-1距离的节点指针
ListNode* GetMid(ListNode*head , int len)
{
ListNode *temp = head;
for (int i = 1; i< len; i++)
{
head = head->next;
}
return head;
} //归并排序
ListNode* MergeSort(ListNode* head, int len)
{
if (len == 1)
{
return head;
}
int mid = len/2;
ListNode *secondHead = GetMid(head, mid+1);
head = MergeSort(head, mid);
secondHead = MergeSort(secondHead,len-mid);
head = CombinList(head,mid,secondHead,len-mid);
return head;
} //为了降低储存空间,仅仅有破坏链表的原有结构,重组链表达到排序的目的
ListNode* CombinList(ListNode *pList1,int len1, ListNode* pList2,int len2)
{
int sum = len1+len2;
ListNode* retHead = NULL;
ListNode* retTail = NULL;
ListNode* nextLink = GetMid(pList2,len2+1); //指向下一条链表的头结点
ListNode * exList = NULL; //用于指向交互结点的指针 if (pList1->val > pList2->val) //确定返回的头结点
{
retHead = pList2;
pList2 = pList2->next;
len2--;
}
else
{
retHead = pList1;
pList1 = pList1->next;
len1--; }
retTail = retHead;
while (len1 != 0 && len2 != 0)
{
if (pList1->val > pList2->val)
{
retTail->next = pList2;
retTail= retTail->next;
pList2 = pList2->next;
len2--;
}
else
{
retTail->next = pList1;
retTail=retTail->next;
pList1 = pList1->next;
len1--;
}
} if (len1 == 0)
{
retTail->next = pList2;
}
else
{
retTail->next = pList1;
while (len1 > 1)
{
pList1= pList1->next;
len1--;
}
pList1->next = nextLink;
}
return retHead;
} //获取链表的长度,时间复杂度为n
int GetLen(ListNode *head)
{
int len = 0;
while (head!=NULL)
{
len++;
head = head->next;
}
return len;
}
}; void printList(ListNode* head)
{
cout<<endl;
while (head != NULL)
{
cout<<head->val<<" ";
head=head->next; }
cout<<endl;
}
int main()
{
ListNode *head = new ListNode;
ListNode *tail = head;
head->val = 4;
head->next = NULL;
for (int i = 0; i< 19; i++)
{
ListNode* temp = new ListNode;
temp->val = rand()%90;
temp->next = NULL;
tail->next = temp;
tail = tail->next;
}
printList(head);
Solution a;
head = a.sortList(head);
printList(head);
system("pause");
return 0;
}

模拟排序前后结果为:

版权声明:本文博主原创文章,博客,未经同意不得转载。

LeetCode之Sort List的更多相关文章

  1. C#版 - LeetCode 148. Sort List 解题报告(归并排序小结)

    leetcode 148. Sort List 提交网址: https://leetcode.com/problems/sort-list/  Total Accepted: 68702 Total ...

  2. 待字闺中之快排单向链表;leetcode之Sort List

    题目来源.待字闺中.原创@陈利人 .欢迎大家继续关注微信公众账号"待字闺中" 分析:思路和数据的高速排序一样,都须要找到一个pivot元素.或者节点. 然后将数组或者单向链表划分为 ...

  3. LeetCode——Insertion Sort List

    LeetCode--Insertion Sort List Question Sort a linked list using insertion sort. Solution 我的解法,假设第一个节 ...

  4. [LeetCode] Wiggle Sort II 摆动排序

    Given an unsorted array nums, reorder it such that nums[0] < nums[1] > nums[2] < nums[3]... ...

  5. [LeetCode] Wiggle Sort 摆动排序

    Given an unsorted array nums, reorder it in-place such that nums[0] <= nums[1] >= nums[2] < ...

  6. [LeetCode] Insertion Sort List 链表插入排序

    Sort a linked list using insertion sort. 链表的插入排序实现原理很简单,就是一个元素一个元素的从原链表中取出来,然后按顺序插入到新链表中,时间复杂度为O(n2) ...

  7. 【Leetcode】Sort List JAVA实现

    Sort a linked list in O(n log n) time using constant space complexity. 1.分析 该题主要考查了链接上的合并排序算法. 2.正确代 ...

  8. [LeetCode] 148. Sort List 解题思路

    Sort a linked list in O(n log n) time using constant space complexity. 问题:对一个单列表排序,要求时间复杂度为 O(n*logn ...

  9. 【LeetCode】 sort list 单清单归并

    称号:Sort a linked list in O(n log n) time using constant space complexity. 思路:要求时间复杂度O(nlogn) 知识点:归并排 ...

随机推荐

  1. hdu4027(线段树)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=4027 线段树功能:区间修改,区间求和. 分析:因为每个数至多开6次平方就变1了,所以对于每一段全为1的 ...

  2. hdu2457 Trie图+dp

    hdu2457 给定n个模式串, 和一个文本串 问如果修改最少的字符串使得文本串不包含模式串, 输出最少的次数,如果不能修改成功,则输出-1 dp[i][j] 表示长度为i的字符串, 到达状态j(Tr ...

  3. hihocoder第42周 k*N骨牌覆盖(状态dp+矩阵快速幂)

    上周的3*N的骨牌,因为状态只有8中,所以我们可以手算出状态转移的矩阵 但是这周是k*N,状态矩阵不好手算,都是我们改成用程序自动生成一个状态转移的矩阵就行了,然后用这个矩阵进行快速幂即可 枚举枚举上 ...

  4. .NET垃圾回收笔记

    名词 垃圾收集目标 ephemeral GC 发生在Gen 0 和Gen 1 的垃圾收集 Full GC 发生Gen 2 及以上的Gen与LOH的垃圾收集 垃圾收集模式 工作站模式 GC直接发生在内存 ...

  5. ACdream 之ACfun 题解

    A - ACfun Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) SubmitSta ...

  6. Cocos性能优化工具的开发介绍Visual Studio内存泄漏检测工具——Visual Leak Detector

    然后,Windows下有什么好的内存泄漏检測工具呢?微软提供Visual Studio开发工具本身没有什么太好的内存泄漏检測功能.我们能够使用第三方工具Visual Leak Detector(下面简 ...

  7. Windows 8 应用开发 - 挂起与恢复

    原文:Windows 8 应用开发 - 挂起与恢复      Windows 8 应用通常涉及到两种数据类型:应用数据与会话数据.在上一篇提到的本地数据存储就是应用层面的数据,包括应用参数设置.用户重 ...

  8. Win32 Windows编程 九

    资源的使用 1 资源文件 图标 光标 字符串 菜单  加速键 对话框资源位图等等 资源脚本文件 - 扩展名为RC文件 定义了资源和相关文件等信息 资源编译器 - RC.exe 2 图标资源 ICON ...

  9. log4net使用特定的解释

    说明:该程序演示如何使用log4net记录日志信息. log4net它是-known开源组件的日志记录功能.使用log4net可以很容易地将信息记录到文件.控制台.Windows事件日志和数据库(含有 ...

  10. DHCP Option 60 认识

    原文地址: http://blog.163.com/chenqioulin_1983/blog/static/83216232010109104430251/   首先还是看看RFC咋说的吧.DHCP ...