public ListNode mergeKLists(ListNode[] lists){
  if (lists == null || lists.length == 0) {
    return null;
  }
  Queue<ListNode> pq=new PriorityQueue<>(lists.length,null);
  for (  ListNode n : lists) {
    if (n != null) {
      pq.add(n);
    }
  }
  ListNode dummy=new ListNode(0);
  ListNode tail=dummy;
  while (!pq.isEmpty()) {
    tail.next=pq.poll();
    tail=tail.next;
    if (tail.next != null) {
      pq.add(tail.next);
    }
  }
  return dummy.next;
}

public ListNode mergeKLists ( ListNode [ ] lists ) { if ( lists == null || lists . length == 0 ) { return null ; } Queue < ListNode > pq = new PriorityQueue < > ( lists . length , null ) ; for ( ListNode n : lists ) { if ( n != null ) { pq . add ( n ) ; } } ListNode dummy = new ListNode ( 0 ) ; ListNode tail = dummy ; while ( ! pq . isEmpty ( ) ) { tail . next = pq . poll ( ) ; tail = tail . next ; if ( tail . next != null ) { pq . add ( tail . next ) ; } } return dummy . next ; }
heap . o ( k ) + o ( n * log ( k ) ) time , o ( k ) space . keep track of all heads in a heap , so that we know the next value to be inserted in o ( log ( k ) ) time . create a result list head , and poll from the queue to get the next value . keep track of the list ' s tail with a pointer . add the next of what we polled from queue , if it ' s not null .
