[leetCode 148] 排序链表

解题思路

自低向上归并,真的很不好写。快把我写吐了。

主要用到两个函数:

cut,把链表按照长度断成一截一截的;
merge,把两个链表归并。

先把链表断开成长度为1的小链表,然后归并一次;再断开成长度为2的,再归并;再断成4,8,16…

具体处理的时候,不是一次把链表断完再归并,而是先断两节,归并一次,再断两节,再归并一次,用一个tail记录之前的链表的尾部,这样可以在归并之后把链表接上。

所以其实每一次操作的时候,链表是有四节的:第1节是已经归并过的链表,第2,3节是断下来的要归并的链表,第3节是还没处理的链表。

这题真的很恶心。

代码

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
public class Solution {

    public ListNode sortList(ListNode head) {
        int len = 0;
        ListNode dummyHead = new ListNode(0, head);
        ListNode dummy = head;
        while (dummy != null) {
            len++;
            dummy = dummy.next;
        }
        if (len < 2) return head;
        //正式处理
        for (int i = 1; i < len; i *= 2) {
            ListNode cur = dummyHead.next;
            ListNode tail = dummyHead;
            while (cur != null) {
                ListNode left = cur;
                ListNode right = cut(cur, i);
                cur = cut(right, i);
                //把链表接上
                tail.next=merge(left, right);
                while (tail.next!=null) tail=tail.next;
            }
        }
        return dummyHead.next;
    }
    public ListNode cut(ListNode head,int length){
        while (--length>0 && head!=null) {
            head=head.next;
        }
        if (head==null) return null;
        ListNode node = head.next;
        head.next=null;
        return node;
    }
    public ListNode merge(ListNode left,ListNode right){
        ListNode dummyHead=new ListNode();
        ListNode cur= dummyHead;
        while (left!=null && right!=null){
            if (left.val<=right.val){
                cur.next=left;
                left=left.next;
            }else {
                cur.next=right;
                right=right.next;
            }
            cur=cur.next;
        }
        if (left==null) cur.next=right;
        else cur.next=left;
        return dummyHead.next;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值