LeetCode-Sort List 链表排序

原题链接: http://oj.leetcode.com/problems/sort-list/

对链表进行排序,要求的时间复杂度为O(n log n)。nlogn的排序有快速排序、归并排序、堆排序。双向链表用快排比较适合,堆排序也可以用于链表,单向链表适合用归并排序。题目要求的是常数的空间复杂度,因为这里用了递归,如果算上栈空间的话,也要 o(logn)的复杂度。

关于链表的划分,这里使用了快慢指针,从中间节点进行切开成单独的链表。在merge之后又会合并成一个链表。

以下分别用归并排序和快速排序实现(Java),遗憾的是快速排序的实现超时了,毕竟交换数据的次数过多,没有归并排序之家更换指针要快。快速排序的实现大家可以忽略,代码写的不太好。

关于链表的归并排序可参考之前的一篇文章归并排序对链表进行排序

,只是实现比下面这个有些复杂。

1. 归并排序实现

01 public class MergetSortList {
02  
03     public static  ListNode sortList(ListNode head) {
04         if(head == null || head.next == nullreturn head;
05         ListNode slow = head;
06         ListNode fast = head;
07         //用快慢指针找到中间节点
08         while(fast.next != null && fast.next.next != null){
09             slow = slow.next;
10             fast = fast.next.next;
11         }
12         ListNode list2 = slow.next;
13         slow.next = null;
14         head = sortList(head);
15         list2 = sortList(list2);
16         return merge(head, list2);
17     }
18  
19     private static ListNode merge(ListNode list1, ListNode list2) {
20         if(list1 == nullreturn list2;
21         if(list2 == nullreturn list1;
22         ListNode newHead = new ListNode(0);//链表头不存储实际数据
23         ListNode last = newHead;
24         last = newHead;
25         //连接每个节点,只更换指针,因此空间复杂度为O(1)
26         while(list1 != null && list2 != null){
27             if(list1.val < list2.val){
28                 last.next = list1;
29                 list1 = list1.next;
30             }else{
31                 last.next = list2;
32                 list2 = list2.next;
33             }
34             last = last.next;
35         }
36         //最后剩余的部分,直接连接起来即可
37         if(list1 != null) last.next = list1;
38         else if(list2 != null) last.next = list2;
39         return newHead.next;
40     }
41  
42     public static void main(String[] args) {
43         ListNode l1 = new ListNode(8);
44         ListNode l2 = new ListNode(7);
45         ListNode l3 = new ListNode(6);
46         ListNode l4 = new ListNode(5);
47         ListNode l5 = new ListNode(4);
48         ListNode l6 = new ListNode(3);
49  
50         l1.next = l2;
51         l2.next = l3;
52         l3.next = l4;
53         l4.next = l5;
54         l5.next = l6;
55  
56         l1 = sortList(l1);
57  
58         while(l1 != null){
59             System.out.print(l1.val + " ");
60             l1 = l1.next;
61         }
62     }
63 }

2.快速排序实现

01 //以end节点作为pivot进行划分,返回划分的节点的前一个节点
02 public static ListNode partition(ListNode head, ListNode end){
03     int pivot = end.val;
04     ListNode lastSmallNode = null;
05     ListNode tmpHead = head;
06     while(tmpHead != end){
07         if(tmpHead.val < pivot){
08             if(lastSmallNode == null) lastSmallNode = head;
09             else lastSmallNode = lastSmallNode.next;
10             int tmp = lastSmallNode.val;
11             lastSmallNode.val = tmpHead.val;
12             tmpHead.val = tmp;
13         }
14         tmpHead = tmpHead.next;
15     }
16     //有可能是划分的节点就是第一个,此时返回null
17     if(lastSmallNode == null){
18         end.val = head.val;
19         head.val = pivot;
20         return null;
21     }else{
22         end.val = lastSmallNode.next.val;
23         lastSmallNode.next.val = pivot;
24         return lastSmallNode;
25     }
26 }
27  
28 public  static void quickSort(ListNode head, ListNode end){
29     if( head == null || head == end || end == null || head.next == nullreturn;
30     ListNode mid = partition(head, end);
31     quickSort(head, mid);
32     //空表示,划分点是第一个位置
33     if(mid == null)
34         quickSort(head.next, end);
35     //如果划分点是最后一个位置,就无需再排序
36     else if(mid != end && mid.next != null && mid.next != end)
37         quickSort(mid.next.next, end);
38 }
39  
40 public static  ListNode sortList(ListNode head) {
41     if(head == null || head.next == nullreturn head;
42     ListNode tail = head;
43     while(tail.next != null)
44         tail = tail.next;
45     quickSort(head,tail);
46     return head;
47 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值