题解 | 单链表的排序

单链表的排序

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

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param head ListNode类 the head node
     * @return ListNode类
     */
    
    // public ListNode[] segList(ListNode head) {
    //     if (head == null || head.next == null) {
    //         return new ListNode[] {head, null};
    //     }
    //     // 两个节点的没有处理好
    //     ListNode fast = head;
    //     ListNode slow = head;
    //     if (head.next.next == null) {
    //         fast = head.next;
    //         slow.next = null;
    //         return new ListNode[] {slow, fast};
    //     }
    //     while (fast != null && fast.next != null) {
    //         slow = slow.next;
    //         fast = fast.next.next;
    //     }
    //     ListNode nextNode = slow.next;
    //     slow.next = null;
    //     ListNode slow_list = head;
    //     ListNode fast_list = nextNode;
    //     System.out.println("slow_list");
    //     System.out.println("fast_list\n");
    //     return new ListNode[] {slow_list, fast_list};
    // }

    public ListNode[] segList(ListNode head) {
        ListNode fast = head;
        ListNode slow = head; //4,5
        if (head == null || head.next == null) {
            return new ListNode[] {head, null};
        }
        //fast有next的前提是next存在
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        //找到slow的前一个节点
        ListNode newHead = head;
        while (newHead.next != slow && newHead.next != null) {
            newHead = newHead.next;
        }
        newHead.next = null;
        System.out.println("slow_list");
        System.out.println("fast_list\n");
        return new ListNode[] {head, slow};
    }
    public ListNode merge(ListNode slow, ListNode fast) {
        ListNode dummy = new ListNode(0);
        ListNode m = dummy;
        ListNode p = slow;
        ListNode q = fast;
        //  9410 765  014 5679  79
        while (p != null && q != null) {
            if (p.val <= q.val) {
                m.next = p;
                m = p;
                p = p.next;

            } else {
                m.next = q;
                m = q;
                q = q.next;
            }
        }
        if (p != null) {
            m.next = p;
        }
        if (q != null) {
            m.next = q;
        }


        return dummy.next;
    }

    public ListNode sortInList(ListNode head) {
        //忘记设置递归终止条件
        if (head == null || head.next == null) {
            return head;
        }
        ListNode[] list_set = segList(head);
        ListNode slow_list = list_set[0];
        ListNode fast_list = list_set[1];
        ListNode new_slow_list = sortInList(slow_list);
        System.out.println("new_slow_list\n\n");
        ListNode new_fast_list = sortInList(fast_list);
        System.out.println("new_fast_list\n\n");
        return  merge(new_slow_list, new_fast_list);

    }
}

单链表排序 ,要求时间复杂度为nlogn,选择了归并排序。归并排序的核心是不断将两个有序列表合并。在链表中要实现一个分割链表的函数来辅助归并排序的实现。可行的方法是采用快慢指针。如果链表结点是奇数 比如 1 2 3 最终slow指向中间节点,如果是偶数,则将链表均分为两个子链表,slow指向第二个链表的第一个节点。分割的时候踩了一个坑,为了减少一次遍历(去找到slow的前一个节点,然后断开连接),我采用了直接将slow.next 作为第二个链表的开始,具体写法是 下面,但是导致了对于两个节点的子链表 无法分割 从而导致报错。 后面换成将slow的前一个节点和slow断开 ,成为两个链表,则没有这个问题 。但是写法还是不够简练,其实在移动slow和fast的过程就可以定位slow的前一个节点。

同时方法用到了 递归,一定要考虑递归的终止条件

此外,如果需要用到尾插法,可以设置一个虚拟节点dummy 到时候直接返回dummy.next.

头插法好像只有在翻转链表的时候更方便一点^_^hhhhh ,明天再写一遍 使用迭代!!!!

// public ListNode[] segList(ListNode head) {
//     if (head == null || head.next == null) {
//         return new ListNode[] {head, null};
//     }
//     // 两个节点的没有处理好
//     ListNode fast = head;
//     ListNode slow = head;
//     if (head.next.next == null) {
//         fast = head.next;
//         slow.next = null;
//         return new ListNode[] {slow, fast};
//     }
//     while (fast != null && fast.next != null) {
//         slow = slow.next;
//         fast = fast.next.next;
//     }
//     ListNode nextNode = slow.next;
//     slow.next = null;
//     ListNode slow_list = head;
//     ListNode fast_list = nextNode;
//     System.out.println("slow_list");
//     System.out.println("fast_list\n");
//     return new ListNode[] {slow_list, fast_list};
// }

全部评论
点赞 回复 分享
发布于 03-01 11:08 广东

相关推荐

06-20 17:42
东华大学 Java
凉风落木楚山秋:要是在2015,你这简历还可以月入十万,可惜现在是2025,已经跟不上版本了
我的简历长这样
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务