NC51:合并k个已排序的链表

合并k个已排序的链表

http://www.nowcoder.com/questionTerminal/65cfde9e5b9b4cf2b6bafa5f3ef33fa6

解法1:优先级队列
优先级队列:小根堆

    PriorityQueue<Integer> queue=new PriorityQueue<>(new Comparator<Integer>(){
        public int compare(Integer a,Integer b){
            return a.compareTo(b);
        }
    });
//  PriorityQueue<Integer> queue = new PriorityQueue();
最小k个数:大根堆
PriorityQueue<Integer> maxHeap=new PriorityQueue<Integer>(k,new Comparator<Integer>(){
        @Override
        public int compare(Integer o1,Integer o2){
                return o2.compareTo(o1);
            }
        });
PriorityQueue<Integer> maxHeap=new PriorityQueue<Integer>(k,(a,b)->b.compareTo(a));     

代码:

import java.util.PriorityQueue;
import java.util.ArrayList;
import java.util.Comparator;
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode mergeKLists(ArrayList<ListNode> lists) {
        if(lists == null || lists.size() < 0){
           return null;
       }
        PriorityQueue<Integer> queue=new PriorityQueue<>(new Comparator<Integer>(){
            public int compare(Integer a,Integer b){
                return a.compareTo(b);
            }
        });
//         PriorityQueue<Integer> queue = new PriorityQueue();
        for(ListNode node : lists){
            while(node != null){
                queue.add(node.val);
                node = node.next;
            }
        }
        ListNode res = new ListNode(0);
        ListNode tmp= res;
        while(!queue.isEmpty()){
            ListNode temp = new ListNode(queue.poll());
            tmp.next = temp;
            tmp = tmp.next;
        }
        return res.next;
    }
}

解法2:递归
如果表1当前值小于表2当前值,表1当前值成为新链表的表头,否则返回表2的当前值作为新链表的表头。 比较当前链表的值,较小的取其子链表继续递归。
当有一个链表取到子链表为空时,说明已经比较完成,可以直接返回非空的链表,返回值赋给了l1.next或者l2.next,但无论如何,最终还是沿着递归链不断返回,最终返回的是新有序链表的表头。

    public ListNode mergeKLists(ArrayList<ListNode> lists) {
        ListNode result=null;
        for(ListNode list : lists){
            result=MergeList(result,list);
        }
        return result;
    }
    public ListNode MergeList(ListNode list1,ListNode list2){
        if(list1==null){
            return list2;
        }
        if(list2==null){
            return list1;
        }

        ListNode newHead=null;
        if(list1.val>list2.val){
            newHead=list2;
            list2.next=MergeList(list1,list2.next);
        }
        else{
            newHead=list1;
            list1.next=MergeList(list1.next,list2);
        }
        return newHead;
    }

解法3:递归+归并排序的思路

public ListNode mergeKLists(ArrayList<ListNode> lists) {
        if(lists == null || lists.length == 0){
            return null;
        }
        return mergeList(lists, 0, lists.length - 1);
    }

    public ListNode mergeList(ListNode[] lists, int left, int right){
        if(left >= right)
            return lists[left];
        int mid = left + (right - left) / 2;
        ListNode l1 = mergeList(lists, left, mid);
        ListNode l2 = mergeList(lists, mid + 1, right);
        return merge(l1, l2);
    }

    public ListNode merge(ListNode l1, ListNode l2){
        if(l1 == null) return l2;
        if(l2 == null) return l1;
        ListNode ans = new ListNode(0);
        ListNode p = ans;
        while(l1 != null && l2 != null){
            if(l1.val <= l2.val){
                p.next = l1;
                l1 = l1.next;
            }
            else{
                p.next = l2;
                l2 = l2.next;
            }
            p = p.next;
        }
        p.next = l1 == null? l2 : l1;
        return ans.next;
    }

解法4:循环遍历
思路: 已经解决了两个排序链表的问题,则k个链表的排序也进行依次遍历即可解决;
因为两个链表合并的时间复杂度是O(n),空间复杂度是O(1);
k个链表是外加一次循环,所以时间复杂度为O(n*m)
(n为lists数组的长度,m为数组中链表的长度),空间复杂度为O(1)

    public ListNode mergeKLists(ArrayList<ListNode> lists) {
        ListNode result=null;
        for(ListNode list : lists){
            result=MergeList(result,list);
        }
        return result;
    }
    public ListNode MergeList(ListNode l1,ListNode l2){
        ListNode tmp = new ListNode(-1);
        ListNode cur = tmp;
        while(l1 != null && l2 != null) {
            if(l1.val < l2.val) {
                cur.next = l1;
                l1 = l1.next;
            }
            else {
                cur.next = l2;
                l2 = l2.next;
            }
            cur = cur.next;
        }
        if(l1 == null) cur.next = l2; 
        // l1遍历为空 那么l2还有节点呢,所以指向l2的节点。

        if(l2 == null) cur.next = l1; 
        // l2遍历为空 那么l1还有节点呢,所以指向l1的节点。

        return tmp.next;
    }
名企高频面试算法题解 文章被收录于专栏

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

全部评论

相关推荐

勤奋努力的椰子这就开摆:美团骑手在美团工作没毛病
投递美团等公司10个岗位
点赞 评论 收藏
分享
点赞 评论 收藏
分享
11-27 17:08
已编辑
牛客_产品运营部_私域运营
腾讯 普通offer 24k~26k * 15,年包在36w~39w左右。
点赞 评论 收藏
分享
评论
1
1
分享
牛客网
牛客企业服务