LeetCode刷题笔记 23(涉及优先队列 链表 递归)

题目:合并 k 个排序链表,返回合并后的排序链表。
eg:输入:
[
1->4->5,
1->3->4,
2->6
]
输出: 1->1->2->3->4->4->5->6

答案:
方法一:将所有元素放进一个数组中,将数组排序后,返回一个新的链表

class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        ListNode Head = new ListNode(0);
        ListNode p = Head;
        int n=0,i=0;
        for(ListNode l:lists){  //计算总长度
            while(l!=null){
                l = l.next;
                n++;
            }
        }
        int[] myList = new int[n];
        for(ListNode l:lists){   //将所有元素放入数组中
            while(l!=null){
                myList[i] = l.val;
                l = l.next;
                i++;
            }
        }
        Arrays.sort(myList); //排序
        for(int x:myList){  //建立新的链表
            p.next = new ListNode(x);
            p = p.next;
        }
        return Head.next;        
    }
}

方法二:
使用优先队列PriorityQueue。
Java中PriorityQueue通过二叉小顶堆实现。优先队列的作用是能保证每次取出的元素都是队列中权值最小的

public ListNode mergeKLists(ListNode[] lists) {
        if (lists == null || lists.length == 0) {
            return null;
        }
        PriorityQueue<Integer> queue = new PriorityQueue<>();
        for (ListNode node : lists) {  //将所有元素插入优先队列
            while (node != null) {
                queue.offer(node.val);
                node = node.next;
            }
        }
        return getNode(queue);
    }

    private  ListNode getNode(PriorityQueue<Integer> queue) {
        if (!queue.isEmpty()) {
            ListNode node = new ListNode(queue.poll());  //poll():移除并返问队列头部(删除前)的元素
            node.next = getNode(queue);
            return node;
        }
        return null;
    }

方法三:
以合并两个有序链表为基础,进行多个链表的合并


class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
    	return merge(lists, 0, lists.length - 1);
    }
    public ListNode merge(ListNode[] lists, int i, int j) {
    	if(j < i) return null;
    	if(i == j) return lists[i];
    	if(j > i + 1) {
    		return baseMerge(merge(lists, i, (i+j)/2), merge(lists, ((i+j)/2)+1, j)); //融合分而治之
    	}
    	ListNode l1 = lists[i];// i+1=j时
    	ListNode l2 = lists[j];
    	return baseMerge(l1,l2);
    }
    public ListNode baseMerge(ListNode l1, ListNode l2) {  //合并两个链表
    	if(l1 == null) return l2;
    	if(l2 == null) return l1;
    	ListNode start = l1.val < l2.val ? l1 : l2;
    	ListNode nonStart = l1.val < l2.val ? l2 : l1;
    	start.next = baseMerge(start.next,nonStart);
    	return start;
    }
}
class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if(lists.length < 1)
            return null;
        ListNode node = merge(lists,0,lists.length - 1);
        return node;
    }
    public ListNode merge(ListNode[] lists, int L, int R){
        if(L == R)
            return lists[L];
        int mid = L + ((R-L) >> 1);
        ListNode node1 = merge(lists,L,mid);  //合并左半部分列表
        ListNode node2 = merge(lists,mid+1,R);//合并右半部分列表
        ListNode node = mergeTwoList(node1,node2);//合并两段已经合并好的列表
        return node;
    }
    private ListNode mergeTwoList(ListNode l1, ListNode l2){ //合并两个列表
        if(l1 == null) return l2;
        if(l2 == null) return l1;
        ListNode node;
        if(l1.val < l2.val){
            node = new ListNode(l1.val);
            node.next = mergeTwoList(l1.next,l2);
        } else {
            node = new ListNode(l2.val);
            node.next = mergeTwoList(l1,l2.next);
        }
        return node;
    }
}

需要注意的地方:

  1. 数组必须提前定义长度
  2. 充分运用递归的思想
  3. 学会将问题分解
  4. PriorityQueue的使用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值