NC70:单链表的排序

单链表的排序

http://www.nowcoder.com/practice/f23604257af94d939848729b1a5cda08

解法1:归并排序

思路:先利用快慢指针找出链表的中点,然后分为两个链表,一直分,知道无法分为止,然后自底而上排序归并

public ListNode sortInList (ListNode head) {
        // write code here
        return mergerSort(head);
    }
    public ListNode mergerSort(ListNode head){
        if(head == null || head.next == null){
            return head;
        }
        ListNode slow = head;
        ListNode fast = head;
        ListNode  pre = null;
        while(fast != null && fast.next != null){
            pre=slow;
            slow = slow.next;
            fast = fast.next.next;
        }
        //       slow
        //       mid next
        // 1 3 4 [5] | 6  7 4 2
        pre.next = null;
        ListNode left = mergerSort(head);
        ListNode right = mergerSort(slow);

        return mergeList(left, right);
    }
     // dh ->
     // 1 2 3 4
     // 6 7 8 9
     public ListNode mergeList(ListNode left, ListNode right){
         ListNode dummyHead = new ListNode(0);
         ListNode cur = dummyHead;
        //ListNode cur = left.val < right.val ? left : right;

         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;
         }
         cur.next = left == null ? right : left;

         return dummyHead.next;
    }

解法2:选择排序

1.建立哨兵节点
2.每次从未排序的链表节点中找出最小的节点接到已排序链表的后面

public ListNode sortInList (ListNode head) {
    if (head == null || head.next == null) {
        return head;
    }

    ListNode dummy = new ListNode(-1);
    dummy.next = head;
    ListNode sorted = dummy;

    while (sorted.next != null) {
        ListNode pre = sorted;
        ListNode cur = sorted.next;
        ListNode preMin = null;
        ListNode min = null;
        while (cur != null) {
            if (min == null || cur.val < min.val) {
                preMin = pre;
                min = cur;
            }
            pre = pre.next;
            cur = cur.next;
        }

        preMin.next = min.next;
        min.next = sorted.next;
        sorted.next = min;
        sorted = min;
    }
    return dummy.next;
}

解法3:虚假的选择排序:交换链表中的值

public ListNode sortInList (ListNode head) {
    if (head == null || head.next == null) {
        return head;
    }

    ListNode move = head;
    while (move.next != null) {
        ListNode temp = move.next;
        while (temp != null) {
            if (temp.val < move.val) {
                int val = temp.val;
                temp.val = move.val;
                move.val = val;
            }
            temp = temp.next;
        }
        move = move.next;
    }
    return head;
}
名企高频面试算法题解 文章被收录于专栏

牛客题霸 - 程序员面试高频题 - 题解

全部评论
问下, 在归并排序的拆分方法里面为什么要使用pre=null呢,既然pre=slow的话,直接用slow.next=null截断链表也是可以的吧?不是很理解这里为什么要用一个辅助node pre
点赞 回复 分享
发布于 2021-06-30 20:37

相关推荐

01-29 16:08
已编辑
华南农业大学 Java
点赞 评论 收藏
分享
点赞 评论 收藏
分享
评论
点赞
1
分享

创作者周榜

更多
牛客网
牛客企业服务