LeetCode Sort List 链表排序(规定 O(nlogn) )


Status: Accepted
Runtime: 66 ms

题意:根据给出的单链表,用O(nlogn)的时间复杂度来排序。由时间复杂度想到快排、归并这两种排序。本次用的是归并排序。递归将链表的规模不断二分到只剩下1或2个元素为止,这也是递归出口,一旦出现这两种情况就可以返回。这里有个问题,链表也能二分?可以的,只是麻烦了些,用两个指针可以实现找到中点。本次代码没有详细分析具体的复杂度,但确实是归并。

注意:要考虑空链表,单个元素的链表,以及多个元素的链表。

 

LeetCode的代码:

技术分享
 1 /**
 2  * Definition for singly-linked list.
 3  * struct ListNode {
 4  *     int val;
 5  *     ListNode *next;
 6  *     ListNode(int x) : val(x), next(NULL) {}
 7  * };
 8  */
 9 class Solution {
10 public:
11     ListNode *sorted(ListNode *head) {
12         //递归出口
13         if(!head->next)    return head;
14         if(!head->next->next)    //只有两个结点时就可以排序并返回了
15         {
16             if(head->val > head->next->val )
17             {
18                 head->next->next=head;
19                 head=head->next;
20                 head->next->next=0;
21             }
22             return head;
23         }        
24         
25         //找中点。方法:p2每往后移2步,p1就移1步,当p2到达最后一个结点时,p1刚好在中间
26         ListNode *p1=head,*p2=head;
27         while(p2)
28         {
29             if(p2->next)
30             {
31                 p2=p2->next->next;    //允许p2为空,但若p2->next为空,则p2->next->next会出错
32                 p1=p1->next;
33             }
34             else    break;
35         }
36         ListNode * sec=p1->next;    //左一半的最后一个结点的next必须为空,此举是必须的
37         p1->next=0;
38         
39         //二分递归
40         ListNode * temp1=sorted(head);
41         ListNode * temp2=sorted(sec);
42         
43         //归并,且返回
44         ListNode * sorted_head=NULL,*sorted_rear=NULL,*jus=NULL;
45         if(temp1->val < temp2->val )    //初始化链表头尾
46         {
47             sorted_head=sorted_rear=temp1;
48             temp1=temp1->next;
49             jus=temp1;    //jus摆在刚减少元素的那个链表,以方便判断是否该链表已没有元素了
50         }
51         else
52         {
53             sorted_head=sorted_rear=temp2;
54             temp2=temp2->next;
55             jus=temp2;
56         }
57         while(jus)    //两个链表都非空
58         {
59             if(temp1->val < temp2->val)
60             {
61                 sorted_rear->next=temp1;
62                 temp1=temp1->next;
63                 jus=temp1;
64             }
65             else
66             {
67                 sorted_rear->next=temp2;
68                 temp2=temp2->next;
69                 jus=temp2;
70             }
71             sorted_rear=sorted_rear->next;
72         }
73         if(!temp1)    //temp1为空
74             sorted_rear->next=temp2;
75         else
76             sorted_rear->next=temp1;
77         return sorted_head;
78     }
79     
80     ListNode *sortList(ListNode *head) {
81         if(!head)    return 0;
82         if(head->next==NULL)    return head;
83         return sorted(head);
84     }
85 };
Sort list

 

可自己测试的代码:

技术分享
  1 #include <iostream>
  2 using namespace std;
  3 
  4 struct ListNode {
  5     int val;
  6     ListNode *next;
  7 };
  8 
  9 ListNode *sorted(ListNode *head) {
 10     //递归出口
 11     if(!head->next)    return head;
 12     if(!head->next->next)    //只有两个结点时就可以排序并返回了
 13     {
 14         if(head->val > head->next->val )
 15         {
 16             head->next->next=head;
 17             head=head->next;
 18             head->next->next=0;
 19         }
 20         return head;
 21     }        
 22     
 23     //找中点。方法:p2每往后移2步,p1就移1步,当p2到达最后一个结点时,p1刚好在中间
 24     ListNode *p1=head,*p2=head;
 25     while(p2)
 26     {
 27         if(p2->next)
 28         {
 29             p2=p2->next->next;    //允许p2为空,但若p2->next为空,则p2->next->next会出错
 30             p1=p1->next;
 31         }
 32         else    break;
 33     }
 34     ListNode * sec=p1->next;    //左一半的最后一个结点的next必须为空,此举是必须的
 35     p1->next=0;
 36     
 37     //二分递归
 38     ListNode * temp1=sorted(head);
 39     ListNode * temp2=sorted(sec);
 40     
 41     //归并,且返回
 42     ListNode * sorted_head=NULL,*sorted_rear=NULL,*jus=NULL;
 43     if(temp1->val < temp2->val )    //初始化链表头尾
 44     {
 45         sorted_head=sorted_rear=temp1;
 46         temp1=temp1->next;
 47         jus=temp1;    //jus摆在刚减少元素的那个链表,以方便判断是否该链表已没有元素了
 48     }
 49     else
 50     {
 51         sorted_head=sorted_rear=temp2;
 52         temp2=temp2->next;
 53         jus=temp2;
 54     }
 55     while(jus)    //两个链表都非空
 56     {
 57         if(temp1->val < temp2->val)
 58         {
 59             sorted_rear->next=temp1;
 60             temp1=temp1->next;
 61             jus=temp1;
 62         }
 63         else
 64         {
 65             sorted_rear->next=temp2;
 66             temp2=temp2->next;
 67             jus=temp2;
 68         }
 69         sorted_rear=sorted_rear->next;
 70     }
 71     if(!temp1)    //temp1为空
 72         sorted_rear->next=temp2;
 73     else
 74         sorted_rear->next=temp1;
 75     return sorted_head;
 76 }
 77 
 78 ListNode *sortList(ListNode *head) {
 79     if(!head)    return 0;
 80     if(head->next==NULL)    return head;
 81     return sorted(head);
 82 }
 83 
 84 
 85 
 86 
 87 
 88 
 89 int main()
 90 {
 91     
 92     ListNode * head=new(ListNode);
 93     head->val=11;    //链表有1个元素
 94     head->next=NULL;
 95     ListNode * p=head;
 96     ListNode * temp=NULL;
 97 
 98     //int a[11]={2,1,3,6,5,8,4,9,7,10};
 99     int a[11]={2,6};    //元素自己随意添加
100     for(int i=0;i<2;i++)    //在这里控制元素个数。
101     {
102         temp=new(ListNode);
103         temp->val=a[i];
104         temp->next=NULL;
105         p->next=temp;
106         p=p->next;
107     }
108     p=sortList(head);
109     while(p)
110     {
111         printf("%d\n",p->val);
112         p=p->next;
113     }
114 
115     return 0;
116 }
Test Code

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。