这个题目思路不算很复杂,但是容易出错,leetcode把它算作hard模式的题目,我看在medium在hard之间,不过如果面试的时候碰到,也就坑死爹。
思路如下:
假设每个链表从小到大排列,头是最小值,则每次从所有链表头中找出最小值, 然后把它摘下来,放到结果链表中,从k个值中找到最小值,不是个难事,不过如果每次都去计算,哪怕用一次冒泡,算法复杂度也是够呛的,因为摘下来后最小值又要重算更新,所以思路是以空间换时间,额外用一个链表记录当前所有链表头的值,该链表维持大小顺序,那么每次更新该链表时,只要找到一个合适的位置插入即可,为了使得这个插入动作不至于是O(n)的时间复杂度,可使用二分法查找插入点(一开始我没用二分法,也能完成功能,但是时间复杂度就直接过不了leetcode oj)。 所以接下来的操作,就是循环取最小链表头,更新最小值链表队列,直到最小值链表队列为空。代码如下(注意,这个代码是我在eclipse里跑的,不能直接贴到 leetcode里,要贴的话需要自己把相应的函数copy过去):
import java.util.ArrayList;
import java.util.List;
public class test {
private static class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
private static class MyPair{
int index;
int ln;
MyPair(int i, int n){
this.index = i;
this.ln = n;
}
}
private static void orderInsert(List<MyPair> orderList, MyPair val){
if(orderList.isEmpty()){
orderList.add(val);
}else{
int end = orderList.size()-1;
innerInsert( orderList, val, 0, end);
// int i = 0;
// while(i<orderList.size() && orderList.get(i).ln<=val.ln){
// i++;
// }
// orderList.add(i, val);
}
}
private static void innerInsert( List<MyPair> orderList, MyPair val, int start, int end){
if(start>end){
return;
}
if(start==end){
if(orderList.get(start).ln<val.ln){
orderList.add(start+1, val);
}else{
orderList.add(start, val);
}
return;
}
int mid = (start+end)/2;
if(orderList.get(mid).ln<val.ln){
innerInsert(orderList, val, mid+1, end);
}else{
innerInsert(orderList, val, start, mid);
}
}
public static ListNode mergeKLists(ListNode[] lists) {
ListNode result = null;
List<MyPair> orderList = new ArrayList();
// initialize oderlist
int index = 0;
for(ListNode ln: lists){
if(ln!=null){
orderInsert(orderList, new MyPair(index, ln.val));
}
index++;
}
//update oderlist by doing the 3 steps:
// 1. get the first element in orderlist, remove head and add it to result from the corresponding index list
// 2. remove first element from oder list
// 3. update oderlist by orderInsert from the updated list new head if new head is not null
// 4. go back to step1, until order list is empty
while(!orderList.isEmpty()){
int currentMin = orderList.get(0).index;
ListNode minList = lists[currentMin];
if(minList==null){
orderList.remove(0);
continue;
}
if(result==null){
lists[currentMin] = minList.next;
result = minList;
minList.next = null;
}else{
lists[currentMin] = minList.next;
minList.next = result;
result = minList;
}
orderList.remove(0);
if(lists[currentMin]!=null){
orderInsert(orderList, new MyPair(currentMin, lists[currentMin].val));
}
}
return revert(result);
// return result;
}
private static ListNode revert(ListNode result){
if(result == null){
return result;
}
ListNode inode = result;
if(inode.next==null){
//single node
return result;
}
ListNode jnode=inode.next;
inode.next = null;
while(true){
ListNode tmpNode = jnode.next;
if(tmpNode == null){
jnode.next = inode;
result = jnode;
return result;
}
jnode.next = inode;
inode = jnode;
jnode=tmpNode;
}
}
public static void myIterate(ListNode ln){
ListNode p = ln;
while(p!=null){
System.out.println(p.val);
p = p.next;
}
System.out.println("=============");
}
public static void main(String[] args) throws Exception {
ListNode n11 = new ListNode(1);
ListNode n12 = new ListNode(2);
ListNode n13 = new ListNode(3);
n11.next = n12;
n12.next = n13;
ListNode n21 = new ListNode(4);
ListNode n22 = new ListNode(8);
ListNode n23 = new ListNode(9);
n21.next = n22;
n22.next = n23;
ListNode n31 = new ListNode(5);
ListNode n32 = new ListNode(6);
ListNode n33 = new ListNode(7);
n31.next = n32;
n32.next = n33;
ListNode[] ll = {n11, n21, n31};
ListNode result = mergeKLists(ll);
myIterate(result);
/*
List<String> tt = new ArrayList();
tt.add("a");
tt.add("b");
tt.add("c");
tt.add(3, "d");
System.out.println(tt);*/
}
}