您的位置:首页 > 其它

LeetCode—Sort List解题报告

2013-12-19 15:21 501 查看
转载请注明:http://blog.csdn.net/ict2014/article/details/17416115

原题如下:



题目解析:

       题目要求是对单链表进行从小到大排序,要求的时间复杂度为O(nlogn)。

       从时间复杂度上分析此题,可以排除插入排序等O(n^2)的算法。

       剩余两种排序算法,快速排序和合并排序。这两种算法究竟使用哪一个呢?此时我们要结合题目的数据结构——单链表进行分析,看哪一个更加方便快捷。快速排序的思想是选定一个pivot点,在该点之前的都小于此点,在该点之后的都大于此点,然后前半部分和后半部分分别递归排序,繁杂的操作就是调整指针。对于合并排序而言,从中间将链表拆分成两个链表,两个链表单独进行排序,排序后的两个链表进行合并操作即可。相比较而言,个人感觉合并排序比较简单一些,拆分成两个链表的时候,从链表的中间进行切分即可,合并两个有序的单链表也是很简单的操作。

题目代码:

       我们实现合并排序,算法的时间复杂度为O(nlogn)。代码在leetcode上Accept.

/**
* 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) {
//List is empty or only one node
if(head == NULL || head->next == NULL){
return head;
}
//List size
int size = GetSize(head);
//Combination Sort
return CombinationSort(head, size);
}

//Combination Sort
ListNode* CombinationSort(ListNode* head,
const int& size){
if(size <= 1){
return head;
}

ListNode* head2 = ForwardNSteps(head, size>>1);
ListNode* newHead1 = CombinationSort(head, size>>1);
ListNode* newHead2 = CombinationSort(head2,size-(size>>1));

return CombineTwoList(newHead1, newHead2);
}

//Combine two sorted lists
ListNode* CombineTwoList(ListNode* head1,
ListNode* head2){
ListNode* newhead;
ListNode* current1 = head1;
ListNode* current2 = head2;

if(head1->val < head2->val){
newhead = head1;
current1 = current1->next;
}else{
newhead = head2;
current2 = current2->next;
}

ListNode* pre = newhead;
while(current1 != NULL && current2 != NULL){
if(current1->val < current2->val){
pre->next = current1;
pre = current1;
current1 = current1->next;
}else{
pre->next = current2;
pre = current2;
current2 = current2->next;
}
}

if(current1 != NULL){
pre->next = current1;
}

if(current2 != NULL){
pre->next = current2;
}

return newhead;
}

//move forward N steps
ListNode* ForwardNSteps(ListNode* head,
const int& nsteps){
for(int i = 1; i < nsteps; ++i){
head = head->next;
}
ListNode* head2 = head->next;
head->next = NULL;
return head2;
}

//calculate the length of list
int GetSize(ListNode* head){
int length = 0;
while(head != NULL){
head = head->next;
++length;
}
return length;
}
};


注意程序的第31行,左移右移运算符的优先级小于加减乘除,第一次总是wrong answer,调试之后,才发现

“size-size>>1”的结果始终为0,因此,必须用括号将size>>1括起来。这是一点需要注意的小事项。

程序总体是合并排序的思想,22-34是合并排序的核心代码段。完成拆分、合并操作。75-84完成拆分操作,36-73完成合并两个有序单链表操作。代码只是用英文进行了简单的注释,如有疑问,可以互相讨论。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息