问题链接:https://oj.leetcode.com/problems/merge-k-sorted-lists/
问题描述:Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
问题API:public ListNode mergeKLists(List<ListNode> lists)
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
问题分析:本题其实是一个很经典的k-sort题目,不管是linkedlist还是arraylist,其实本质上都是利用priority queue来处理的例子。leetcode之所以用linkedlist应该是方便我们处理而已,因为如果是arraylist需要处理的还有index。也无法好好地连接起来。
priority_queue本质上就是最小堆,也就是推进去的所有元素,每次pop出来都是最小值,所以首先List中所有的首元素也就是head node都push进priority queue里。
然后循环执行以下的过程:
1. 从priority_queue中pop出队列里的最小值对应的node。然后将这个node连接进结果list里
2.如果这个node之后还有node,就offer进队列里。
直到队列为空的时候,结果链表就构建完成了。
值得注意的是,如果需要利用到PriorityQueue<T> 容易,放进去的类需要实现以下两个东西之一:
1. Comparable接口。(override public int compareTo(T t))
2. Comparator接口。 (override public int compares(T t1, T t2))
下面是实现了Comparable接口的做法:
class Node implements Comparable<Node>{
ListNode curNode;
public Node(ListNode curNode){
this.curNode = curNode;
}
@Override
public int compareTo(Node node){
return (new Integer(this.curNode.val)).compareTo(new Integer(node.curNode.val));
}
}
public class Solution {
public ListNode mergeKLists(List<ListNode> lists) {
Queue<Node> node_queue = new PriorityQueue<Node>();
ListNode head = null, tmp = null;
for(ListNode ln : lists){
if(ln != null){
Node node = new Node(ln);
node_queue.offer(node);
}
}
while(!node_queue.isEmpty()){
Node n = node_queue.poll();
if(head == null){
head = n.curNode;
tmp = head;
}else{
tmp.next = n.curNode;
tmp = tmp.next;
}
if(tmp.next != null){
node_queue.offer(new Node(tmp.next));
}
}
return head;
}
上面的类定义的有点冗余,大家可以想想如何简化
另外下面给出的是实现Comparator的代码,实际上是一样的:
public ListNode mergeKLists(List<ListNode> lists) {
if(lists == null || lists.size() == 0)
return null;
PriorityQueue<ListNode> k_queue = new PriorityQueue<ListNode>(lists.size(), new NodeComparator());
for(int i = 0; i < lists.size(); i++){
if(lists.get(i) != null)
k_queue.add(lists.get(i));
}
ListNode tmp = null, head = null;
while(!k_queue.isEmpty()){
ListNode tmp_node = k_queue.poll();
if(tmp_node.next != null)
k_queue.add(tmp_node.next);
if(head == null){
head = tmp = tmp_node;
}else{
tmp.next = tmp_node;
tmp = tmp.next;
}
}
return head;
}
class NodeComparator implements Comparator<ListNode>{
@Override
public int compare(ListNode n1, ListNode n2){
if(n1.val < n2.val)
return -1;
else if(n1.val == n2.val)
return 0;
else
return 1;
}
}