LeetCode Sort List

25 篇文章 0 订阅
8 篇文章 0 订阅

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

思路分析:这题要求在O(n log n) 和常量空间对单链表排序,O(n log n) 的排序算法有快速排序,归并排序和堆排序,对于快速排序,其最坏情况下的时间复杂读是O(n),所以不符合要求。我们可以用归并排序解决这题。用归并排序的好处是平均时间和最坏时间都是O(n log n) ,并且我们不需要额外空间就可以merge两个有序的链表使得merge之后仍然有序。这里插一句,链表和数组的区别在于链表不支持元素按照index随机访问,因此实现依赖于index访问元素的算法会比较麻烦,但是链表也有其自身的优势,就是在任意位置插入或者删除元素都是常量时间,因为不需要移动大量元素“腾地方”。在数组上实现归并排序和在链表上实现归并排序基本算法一致,都是先不断对半划分数组,直到每个元组只剩下一个元素的时候开始merge元素,递归划分,划分完毕进行merge。下图给出的算法过程的形象表示(来自这里):


划分的过程数组和链表是类似的,只是我们需要找到链表的中点,这个可以用快慢指针法解决。划分完毕后merge的过程二者有不同,对于数组我们会使用额外tmp数组保存merge之后的数组结果,merge结束后拷贝回原来数组。对于链表,我们不需要额外空间,那么如何merge两个有序链表使得merge之后仍然有序呢?这就是LeetCode Merge Two Sorted List 问题,我以merge1 3 5 和 2 4 6的过程为例,单步图解如下


理解了快慢指针找链表中点,merge两个sorted list的过程和merge sort的划分合并过程后,解决这题就很容易了。

AC Code

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode sortList(ListNode head) {
        return mergeSortList(head);
    }
    
    public ListNode mergeSortList(ListNode head) {//split the list into two partitions
        if(head == null || head.next == null) return head;
        ListNode fast = head;
        ListNode slow = head;
        while(fast.next != null && fast.next.next != null){//fast must arrive the end firstly
            fast = fast.next;
            fast = fast.next;
            slow = slow.next;
        }
        ListNode head1 = head;
        ListNode head2 = slow.next;
        slow.next = null;//split the list from the middle node
        head1 = mergeSortList(head1);
        head2 = mergeSortList(head2);
        return merge(head1, head2);
    }
    
    public ListNode merge(ListNode head1, ListNode head2){
        ListNode fakeHead = new ListNode(0);
        fakeHead.next = head1;
        ListNode pre = fakeHead;
        while(head1 != null && head2 != null){
            if(head1.val < head2.val){
                head1 = head1.next;
            } else {
                ListNode next = head2.next;
                head2.next = pre.next;
                pre.next = head2;
                head2 = next;
            }
            pre = pre.next;
        }
        if(head2 != null){
            pre.next = head2;
        }
        return fakeHead.next;
    }
}

解题过程中参考了 http://blog.csdn.net/linhuanmars/article/details/21133949 但是这个解法由于是递归实现,仍然需要(O(logn))的栈空间。迭代实现的解法可以参考 这里

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值