lc148.java 2.9 KB
Newer Older
L
liu13 已提交
1
package code;
L
liu13 已提交
2 3 4 5

import java.util.ArrayList;
import java.util.List;

L
liu13 已提交
6 7 8 9 10 11
/*
 * 148. Sort List
 * 题意:链表排序
 * 难度:Medium
 * 分类:Linked List, Sort
 * 思路:快慢指针把链表分成两半,在merge两个链表
L
liu13 已提交
12 13 14
 *      快排方法自己不会写,记下思路
 *      快排尝试直接以ListNode互相交换位置,节点间的指向会乱掉的,当递归子情况的时候会修改指针,父方法不知道子调用做了哪些操作
 *      https://www.cnblogs.com/morethink/p/8452914.html
L
liu13 已提交
15 16 17 18 19 20 21 22 23 24 25 26 27
 * Tips:空间复杂度不是O(1)的,但是几个高票答案都是这样写的,面试给出这样的代码应该也够了
 */
public class lc148 {
    public class ListNode {
        int val;
        ListNode next;
        ListNode(int x) { val = x; }
    }

    public ListNode sortList(ListNode head) {
        if( head==null || head.next == null ){
            return head;
        }
L
liu13 已提交
28
        ListNode slow = head;   //记一下
L
liu13 已提交
29
        ListNode fast = head.next;
L
liu13 已提交
30
        while( fast!=null && fast.next!=null ){   //把链表分成两半
L
liu13 已提交
31 32 33 34
            slow = slow.next;
            fast = fast.next.next;
        }
        ListNode l2 = sortList(slow.next);
L
liu13 已提交
35
        slow.next = null;   //别忘了这要断开
L
liu13 已提交
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
        ListNode l1 = sortList(head);
        return mergeList(l1, l2);
    }

    public ListNode mergeList(ListNode l1, ListNode l2){
        ListNode res = new ListNode(0);
        ListNode head = res;
        while( l1!=null && l2!=null ){
            if(l1.val<l2.val){
                res.next = l1;
                l1 = l1.next;
                res = res.next;
            }else{
                res.next = l2;
                l2 = l2.next;
                res = res.next;
            }
        }
        if(l1!=null){
            res.next = l1;
        }
        if(l2!=null){
            res.next = l2;
        }
        return head.next;
    }
L
liu13 已提交
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77

    public ListNode sortList2(ListNode head) {  //链表快排
        //采用快速排序
        quickSort(head, null);
        return head;
    }
    public void quickSort(ListNode head, ListNode end) {
        if (head != end) {
            ListNode node = partion(head, end);
            quickSort(head, node);
            quickSort(node.next, end);
        }
    }

    public ListNode partion(ListNode head, ListNode end) {
        ListNode p1 = head, p2 = head.next;
L
liu13 已提交
78
        //p1指的是小于pivot的索引
L
liu13 已提交
79
        //走到末尾才停
L
liu13 已提交
80
        while (p2 != end) { //head到p1间是小于pivot的数,p1与p2间都是大于pivot的数
L
liu13 已提交
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
            if (p2.val < head.val) {    //lc922 类似的思想, 把小于的值放到该放的位置上
                p1 = p1.next;

                int temp = p1.val;
                p1.val = p2.val;
                p2.val = temp;
            }
            p2 = p2.next;
        }

        //与pivot交换下位置
        int temp = p1.val;
        p1.val = head.val;
        head.val = temp;

        return p1;  //返回
    }
L
liu13 已提交
98
}