I came across this problem of merging k sorted lists and my solution simply creates an array with all the elements and sorts the array. I think this solution has O(n log n) time (which seems to be the best you can do with this problem). But maybe I'm wrong. Is this somehow not the right solution or not optimal? The reason I ask is because this is marked as 'hard' problem on Leetcode so I expect there's some complexity I haven't taken into account or that this wasn't the intent of the problem.
# Definition for singly-linked list.
# class ListNode
# attr_accessor :val, :next
# def initialize(val)
# @val = val
# @next = nil
# end
# end
# @param {ListNode[]} lists
# @return {ListNode}
def merge_k_lists(lists)
final_list = []
lists.each do |list|
while list
final_list << list.val
list = list.next
end
end
final_list.sort!
end
EDIT: Now it makes sense that the best algorithm can be O(n log k) and that can be done with a min-heap. Does a divide and conquer give the same time complexity?
Here's my divide and conquer solution, which turns out to be a lot slower than my previous solution. (this one is not an accepted solution since it exceeds the time limit)
def merge_k_lists(lists)
lists.compact!
return lists.first if lists.length == 1
if lists.length > 2
new_lists = []
mid = lists.length/2
new_lists << merge_k_lists(lists[0...2])
new_lists << merge_k_lists(lists[2..-1])
lists = new_lists
end
list_a = lists.first
list_b = lists.last
root = nil
last_node = nil
while list_a || list_b
if !list_b.nil? && (list_a.nil? || list_a.val > list_b.val)
list_b, list_a = list_a, list_b
end
node = ListNode.new(list_a.val)
list_a = list_a.next
if last_node
last_node.next = node
last_node = node
else
root = node
last_node = node
end
end
return root
end