LeetCode Top 100 Liked Questions 23. Merge k Sorted Lists (Java版; Hard)
题目描述
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
Example:
Input:
[
1 - > 4 - > 5 ,
1 - > 3 - > 4 ,
2 - > 6
]
Output: 1 - > 1 - > 2 - > 3 - > 4 - > 4 - > 5 - > 6
class Solution {
public ListNode mergeKLists ( ListNode[ ] lists) {
int n = lists. length;
if ( n== 0 ) {
return null;
}
return mergeSort ( lists, 0 , n- 1 ) ;
}
private ListNode mergeSort ( ListNode[ ] lists, int L, int R) {
if ( L> R) {
return null;
}
if ( L== R) {
return lists[ L] ;
}
int mid = L + ( R- L) / 2 ;
ListNode left = mergeSort ( lists, L, mid) ;
ListNode right = mergeSort ( lists, mid+ 1 , R) ;
return merge ( left, right) ;
}
private ListNode merge ( ListNode node1, ListNode node2) {
ListNode dummy = new ListNode ( - 1 ) ;
ListNode cur = dummy;
while ( node1!= null && node2!= null) {
if ( node1. val < node2. val) {
cur. next = node1;
node1 = node1. next;
cur = cur. next;
} else {
cur. next = node2;
node2 = node2. next;
cur = cur. next;
}
}
if ( node1!= null) {
cur. next = node1;
}
if ( node2!= null) {
cur. next = node2;
}
return dummy. next;
}
}
第二次做; 分治思想; 递归函数逻辑:将lists[left, right]这些链表合并, 先合并完lists[left,mid]这些链表, 再合并完lists[mid+1,right]这些链表, 然后将这两部分合并成一个大链表
class Solution {
public ListNode mergeKLists ( ListNode[ ] lists) {
if ( lists== null || lists. length== 0 )
return null;
ListNode head = mergeSort ( lists, 0 , lists. length- 1 ) ;
return head;
}
private ListNode mergeSort ( ListNode[ ] lists, int left, int right) {
if ( left== right)
return lists[ left] ;
int mid = left + ( ( right- left) >> 1 ) ;
ListNode head1 = mergeSort ( lists, left, mid) ;
ListNode head2 = mergeSort ( lists, mid+ 1 , right) ;
ListNode head = merge ( head1, head2) ;
return head;
}
private ListNode merge ( ListNode head1, ListNode head2) {
if ( head1== null)
return head2;
if ( head2== null)
return head1;
ListNode cur;
if ( head1. val<= head2. val) {
head1. next = merge ( head1. next, head2) ;
return head1;
}
else {
head2. next = merge ( head1, head2. next) ;
return head2;
}
}
}
第一次做, 分治思想; 合并两个链表也可以改成递归的形式; 执行用时4ms ;内存消耗40.9MB; 比不用分治思想的方法快太多了…
class Solution {
public ListNode mergeKLists ( ListNode[ ] lists) {
if ( lists== null || lists. length== 0 )
return null;
return merge ( lists, 0 , lists. length- 1 ) ;
}
public ListNode merge ( ListNode[ ] lists, int left, int right) {
if ( left == right)
return lists[ left] ;
int mid = left + ( ( right - left) >> 1 ) ;
ListNode leftHead = merge ( lists, left, mid) ;
ListNode rightHead = merge ( lists, mid+ 1 , right) ;
ListNode head = mergeTwo ( leftHead, rightHead) ;
return head;
}
public ListNode mergeTwo ( ListNode leftHead, ListNode rightHead) {
if ( leftHead== null)
return rightHead;
if ( rightHead== null)
return leftHead;
if ( leftHead. val < rightHead. val) {
leftHead. next = mergeTwo ( leftHead. next, rightHead) ;
return leftHead;
}
else {
rightHead. next = mergeTwo ( leftHead, rightHead. next) ;
return rightHead;
}
}
}
第一次做, 看了题解后使用分治思想(看来归并就是分治思想; 二分就是分治思想); 执行用时5ms ;内存消耗42.6MB; 比不用分治思想的方法快太多了…
class Solution {
public ListNode mergeKLists ( ListNode[ ] lists) {
if ( lists== null || lists. length== 0 )
return null;
return merge ( lists, 0 , lists. length- 1 ) ;
}
public ListNode merge ( ListNode[ ] lists, int left, int right) {
if ( left == right)
return lists[ left] ;
int mid = left + ( ( right - left) >> 1 ) ;
ListNode leftHead = merge ( lists, left, mid) ;
ListNode rightHead = merge ( lists, mid+ 1 , right) ;
ListNode head = mergeTwo ( leftHead, rightHead) ;
return head;
}
public ListNode mergeTwo ( ListNode leftHead, ListNode rightHead) {
if ( leftHead== null)
return rightHead;
if ( rightHead== null)
return leftHead;
ListNode tempHead = new ListNode ( 0 ) , curr = tempHead;
while ( leftHead!= null || rightHead!= null) {
if ( leftHead. val < rightHead. val) {
curr. next = leftHead;
leftHead = leftHead. next;
curr = curr. next;
}
else {
curr. next = rightHead;
rightHead = rightHead. next;
curr = curr. next;
}
if ( leftHead== null) {
curr. next = rightHead;
break ;
}
if ( rightHead== null) {
curr. next = leftHead;
break ;
}
}
return tempHead. next;
}
}
第一次做,多路归并, 核心思想和二路归并一样, 基础要牢牢掌握; 执行用时43ms ;内存消耗41.9MB
class Solution {
public ListNode mergeKLists ( ListNode[ ] lists) {
if ( lists== null)
return null;
ListNode tempHead = new ListNode ( 0 ) , curr = tempHead;
while ( true ) {
boolean flag = false ;
for ( int i= 0 ; i< lists. length; i++ ) {
flag = flag | ( lists[ i] == null? false : true ) ;
}
if ( flag== false )
break ;
int min = Integer. MAX_VALUE;
for ( int i= 0 ; i< lists. length; i++ ) {
if ( lists[ i] != null)
min = Math. min ( min, lists[ i] . val) ;
}
for ( int i= 0 ; i< lists. length; i++ ) {
if ( lists[ i] != null && lists[ i] . val== min) {
curr. next = lists[ i] ;
lists[ i] = lists[ i] . next;
curr = curr. next;
}
}
}
return tempHead. next;
}
}
题解, 分治法, 两两合并; 想法很漂亮
class Solution {
public ListNode mergeKLists ( ListNode[ ] lists) {
if ( lists == null || lists. length == 0 ) return null;
return merge ( lists, 0 , lists. length - 1 ) ;
}
private ListNode merge ( ListNode[ ] lists, int left, int right) {
if ( left == right) return lists[ left] ;
int mid = left + ( right - left) / 2 ;
ListNode l1 = merge ( lists, left, mid) ;
ListNode l2 = merge ( lists, mid + 1 , right) ;
return mergeTwoLists ( l1, l2) ;
}
private ListNode mergeTwoLists ( ListNode l1, ListNode l2) {
if ( l1 == null) return l2;
if ( l2 == null) return l1;
if ( l1. val < l2. val) {
l1. next = mergeTwoLists ( l1. next, l2) ;
return l1;
} else {
l2. next = mergeTwoLists ( l1, l2. next) ;
return l2;
}
}
}