LeetCode解题报告--Merge k Sorted Lists

本文探讨了如何将多个已排序的链表合并成一个排序链表的问题,并提供了两种解决方案:一种是递归方法,通过两两合并最终得到单一链表;另一种则是使用优先队列的方法,高效地实现了题目的要求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

**题目:**Merge k Sorted Lists

Merge k sorted linked lists and return it as one sorted list. Analyze
and describe its complexity.

分析:题意要求将k个排好序的链表,整合为一个排好序链表,该题是之前的合并两个排好序的链表的延伸,延伸为一般情况。基本思想与两链表合并一样,可参见之前的博客
第一种方法:递归思想,依次两两合并为一个链表,直到合并为一个链表,此处两种思路:

1>从数组遍历开始,相邻的元素两两合并,合并后的链表直接赋值给相邻元素id大那个元素,重复上述过程!如下图示:
这里写图片描述
该方法会出现超时问题,在对时间复杂度要求不高的情况下,可以考虑。

Java NotPass 代码:

//First method: not accept Time Limited Out
    public static ListNode mergerKSortedList(ListNode[] lists) {
        ListNode listNode = new ListNode(0);
        mergerTwoSortedList(listNode, lists.length, lists);
        return listNode.next;
    }

    public static void mergerTwoSortedList(ListNode listNode, int length,
            ListNode[] lists) {
        ListNode p;
        ListNode q;
        ListNode fakeHead;


        if(length == 1 || length == 0){
            return;
        }else{
            fakeHead = listNode;
            p = lists[0];
            q = lists[1];
            while (p != null && q != null) {
                if (p.val <= q.val) {
                    fakeHead.next = p;
                    p = p.next;
                } else {
                    fakeHead.next = q;
                    q = q.next;
                }
                fakeHead = fakeHead.next;
            }

            if (p == null) {
                fakeHead.next = q;
            } else if(q == null) {
                fakeHead.next = p;
            }
            lists[1] = listNode.next;
            ListNode[] list = new ListNode[length - 1];
            for (int i = 0; i < length - 1; i++) {
                list[i] = lists[i + 1];
            }
            mergerTwoSortedList(listNode, list.length, list);
        }
    }

2>基于1>中的思想,考虑用二分法实现俩俩合并,时间复杂度是O(N log K)。如下图示:
这里写图片描述

Java Accepted 代码:

public class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
    if(lists.length == 0){
            return null;
        }
        return mergerKSortedList(lists, 0,lists.length - 1);
    }


    public static ListNode mergerKSortedList(ListNode[] lists,int left,int right){
        if(left < right){
        int mid = (left + right) / 2;
        return  mergerTwoSortedList(mergerKSortedList(lists, left, mid),mergerKSortedList(lists, mid + 1,right));
        }
        return lists[left];
    }
    public static ListNode mergerTwoSortedList(ListNode listNode1,ListNode listNode2) {
        ListNode p;
        ListNode q;
        ListNode fakeHead;
        ListNode head = new ListNode(0);
            fakeHead = head;
            p = listNode1;
            q = listNode2;
            while (p != null && q != null) {
                if (p.val <= q.val) {
                    fakeHead.next = p;
                    p = p.next;
                } else {
                    fakeHead.next = q;
                    q = q.next;
                }
                fakeHead = fakeHead.next;
            }

            if (p == null) {
                fakeHead.next = q;
            } else if(q == null) {
                fakeHead.next = p;
            }
            return head.next;
}

前提:什么是优先队列: 优先级队列是不同于先进先出队列的另一种队列。每次从队列中取出的是具有最高优先权的元素。
  PriorityQueue是从JDK1.5开始提供的新的数据结构接口。
  如果不提供Comparator的话,优先队列中元素默认按自然顺序排列,也就是数字默认是小的在队列头,字符串则按字典序排列。
具体可见Oracle官网介绍:
http://docs.oracle.com/javase/7/docs/api/java/util/PriorityQueue.html

第二种方法:利用优先队列即java自带的PriorityQueue类,该方法最简单直接解决问题,首先将n个链表头节点按指定大小(改写Comparator方法,该方法决定压栈的顺序)压入栈,然后取出栈顶元素,存放到目标链表上,接着再将该节点的下一个元素压入栈,直到所有链表都遍历完成。

Java Accepted 代码:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
            //Special case
        if(lists.length == 0 || lists == null){
            return null;
        }

        Comparator<ListNode> order = new Comparator<ListNode>() {

            public int compare(ListNode o1, ListNode o2) {
                // TODO Auto-generated method stub
                return o1.val - o2.val;
            }
        };
        PriorityQueue<ListNode> p = new PriorityQueue<ListNode>(lists.length,order);

        //New queue in special order
        for(ListNode list: lists){
            if(list != null)
                  p.add(list);
        }

        ListNode head = new ListNode(-1);
        ListNode q = head;
        while(!p.isEmpty()){
            //Retrieves and remove the head of queue 
            ListNode item = p.poll();
            q.next = item;
            //Keep add the next node of item till item is null
            if(item.next != null)
                p.add(item.next);

            q =  q.next;
        }
        return head.next;
        }
}

相关代码放在个人github:https://github.com/gannyee/LeetCode/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值