题解 | #单链表的排序#

思路

使用分治思想,将大问题分割成一个个相同的小问题,假设一个长度为n的无序链表进行排序,我们可以将其分解即将链表一个个断开,变成n个已排序的链表的合并 可以参考BM5. 合并k个已排序的链表

又或者使用快慢指针,将链表从中间截断,一分为二,分别递归的调用方法继续截断,直到最后无法分割,此时会返回两个已排序的链表(实际上就是只有一个元素或者干脆是空的链表) 可以参考BM4. 合并两个有序的链表

代码

import java.util.*;

/*
 * public class ListNode {
 *   int val;
 *   ListNode next = null;
 * }
 */

public class Solution {
   /**
     * @param head ListNode类 the head node
     * @return ListNode类
     */
    public ListNode sortInList(ListNode head) {
        // 健壮性检验
        if (head == null || head.next == null) {
            return head;
        }

        // 准备快慢指针与临时指针
        ListNode fast = head.next.next;
        ListNode slow = head.next;
        // 临时指针用于存储慢指针的上一节点,方便截断
        ListNode temp = head;
        // 使用快慢指针遍历无序链表,当快指针本身为null(链表长度为奇数)或者快指针下一个节点为空(链表长度为偶数)时停止遍历
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
            temp = temp.next;
        }
        // 将链表截断
        temp.next = null;
        // 对前一段链表进行递归,返回已排序的链表
        ListNode list1 = sortInList(head);
        // 对后一段链表进行递归,返回已排序的链表
        ListNode list2 = sortInList(slow);
        // 调用合并方法将有序链表合并
        return merge(list1, list2);
    }

    /**
     * 将传入的两个有序链表合并
     *
     * @param list1 链表1
     * @param list2 链表2
     * @return com.gewuyou.algorithm.problem.ListNode
     * @apiNote
     * @since 2022/12/20 14:05
     */
    public ListNode merge(ListNode list1, ListNode list2) {
        if (list1 == null && list2 == null) {
            return null;
        }
        /*
          思路:
          使用两个队列存储该链表,通过比较两个出队的数据来创建合并后的有序链表
         */
        // 创建两个队列
        Queue<Integer> queue1 = new LinkedList<>();
        Queue<Integer> queue2 = new LinkedList<>();
        // 将链表的数据倒入
        while (list1 != null) {
            queue1.add(list1.val);
            list1 = list1.next;
        }
        while (list2 != null) {
            queue2.add(list2.val);
            list2 = list2.next;
        }
        // 创建一个新头节点
        ListNode head = new ListNode(-1);
        ListNode flagNode = head;

        while (!queue1.isEmpty() && !queue2.isEmpty()) {
            if (queue1.peek() < queue2.peek()) {
                flagNode.next = new ListNode(queue1.poll());
            } else {
                flagNode.next = new ListNode(queue2.poll());
            }
            flagNode = flagNode.next;
        }
        // 如果其中一个队列已经空了,则直接将另一个的值全部放入新链表
        while (!queue1.isEmpty()) {
            flagNode.next = new ListNode(queue1.poll());
            flagNode = flagNode.next;
        }
        while (!queue2.isEmpty()) {
            flagNode.next = new ListNode(queue2.poll());
            flagNode = flagNode.next;
        }
        // 返回链表
        return head.next;
    }
}
全部评论

相关推荐

我已成为0offer的糕手:别惯着,胆子都是练出来的,这里认怂了,那以后被裁应届被拖工资还敢抗争?
点赞 评论 收藏
分享
joe2333:怀念以前大家拿华为当保底的日子
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务