[LeetCode23]Merge k Sorted Lists

本文详细介绍了如何使用递归和优先队列方法合并多个已排序链表,并分析了其时间复杂度为O(knlogn)。通过示例代码展示了合并过程,并对比了不同方法的效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.

While the lists is not empty, keep merging the list to the result list. Method to merge two lists is the same as.

Question 54: Merge Two Sorted Lists

ListNode *merge2Lists(ListNode *head1, ListNode *head2){
        ListNode *head = new ListNode(INT_MIN);
        ListNode *pre = head;
        while(head1 != NULL && head2 != NULL){
            if(head1->val <= head2->val){
                pre->next = head1;
                head1 = head1->next;
            }else{
                pre->next = head2;
                head2 = head2->next;
            }
            pre = pre->next;
        }
        if(head1 != NULL){
            pre->next = head1;
        }
        if(head2 != NULL){
            pre->next = head2;
        }
        pre = head->next;
        delete head;
        return pre;
    }
ListNode *mergeKLists(vector<ListNode *> &lists) {
        if(lists.size() == 0) return NULL;
        ListNode *p = lists[0];
        for(int i=1; i<lists.size(); i++){
            p = merge2Lists(p, lists[i]);
        }
        return p;
    }
java

public ListNode mergeKLists(List<ListNode> lists) {
                ListNode head = new ListNode(-1);
        ListNode p = head;
        if(lists.size()==0) return null;
        if(lists.size()==1) return lists.get(0);
        ListNode l1 = lists.get(0);
        for(int i=1;i<lists.size();i++){
        	ListNode l2 = lists.get(i);
        	while(l1!=null && l2!=null){
        		if(l1.val<l2.val){
        			p.next = l1;
        			l1 = l1.next;
        			p = p.next;
        		}else{
        			p.next = l2;
        			l2 = l2.next;
        			p = p.next;
        		}
        	}
        	while(l1!=null){
        		p.next = l1;
        		p = p.next;
        		l1 = l1.next;
        	}
        	while(l2!=null){
        		p.next = l2;
        		p = p.next;
        		l2 = l2.next;
        	}
        	l1 = head.next;
        	p = head;
        }
        return head.next;
    }

Refactor: Sep/17/2014

Java Recursion

It’s similar to merge sort. For example, assuming we have 4 lists: 1, 2, 3, 4. We can merge 1 and 2 to be a new list 5. And 3 and 4 can be merged to be a new list 6. Finally we merge 5 and 6 to get the result. So in this algorithm, we divide the lists by 2 until its size reaches 1. And then merge them from bottom to top. We have T(n) = 2T(n/2) + kn. So the complexity is O(kn logn). The depth of the recursive function is O(log n).

public ListNode mergeKLists(List<ListNode> lists) {
		if(lists.size()<=0) return null;
		if(lists.size()==1) return lists.get(0);
        return mergeKlists(lists, 0, lists.size()-1);
    }
	public ListNode mergeKlists(List<ListNode> lists, int left, int right){
		if(left<right){
			int mid = left+(right-left)/2;
			return merge2List(mergeKlists(lists, left, mid), mergeKlists(lists, mid+1, right));
		}
		return lists.get(left);
	}
	public ListNode merge2List(ListNode l1, ListNode l2){
		ListNode newHead = new ListNode(-1);
		ListNode p1 = newHead;
		while(l1!=null && l2!=null){
			if(l1.val<=l2.val){
				p1.next = l1;
				l1 = l1.next;
			}else {
				p1.next = l2;
				l2 = l2.next;
			}
			p1 = p1.next;
		}
		p1.next = (l1==null) ? l2:l1;
		return newHead.next;
	}

There is another optimal way using a priority queue. We can add the heads of all lists in to the queue. And we can poll out the smallest one. If the next node of this smallest node is not null, we can add the next node to the queue. We will continue doing this until the queue is empty. Every time we add a new element to the queue, it costs O(log n). And we have k elements. So the complexity is O(k logn) + O(k) = O(k logn). And the space complexity is only O(k). k is the total number of lists, n is length of each linked list.

public ListNode mergeKLists(List<ListNode> lists) {
		Comparator<ListNode> listNodeComparator = new Comparator<ListNode>() {
			
			@Override
			public int compare(ListNode l1, ListNode l2) {
				// TODO Auto-generated method stub
				return l1.val-l2.val;
			}
		};
		if(lists.size()==0) return null;
		Queue<ListNode> pQueue = new PriorityQueue<>(lists.size(), listNodeComparator);
		for(int i=0;i<lists.size();i++){
			if(lists.get(i)!=null){
				pQueue.add(lists.get(i));
			}
		}
		ListNode head = new ListNode(0);
		ListNode p = head;
		while(!pQueue.isEmpty()){
			ListNode node = pQueue.poll();
			p.next = node;
			if(node.next!=null){
				pQueue.add(node.next);
			}
			p = p.next;
		}
		return head.next;
    }





### LeetCode Problem 23: Merge k Sorted Lists 对于这个问题,目标是从给定的`k`个升序链表中合并所有链表并返回一个已排序的链表。可以采用分治法来解决此问题,通过两两合并的方式逐步减少列表数量直到只剩下一个最终的结果链表[^1]。 为了实现这一算法,一种有效的方法是利用优先队列(最小堆)。将每个链表的第一个节点加入到最小堆中;每次从堆顶取出当前最小值作为新链表的一部分,并将其所在原链表中的下一节点继续放入堆中参与后续比较。重复上述过程直至处理完所有的节点。 以下是Python版本的具体代码实现: ```python from typing import List, Optional import heapq class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next # Define comparison methods for heap operations def __lt__(self, other): return self.val < other.val def mergeKLists(lists: List[ListNode]) -> Optional[ListNode]: min_heap = [] # Initialize the heap with head nodes of all lists. for l in lists: if l: heapq.heappush(min_heap, (l.val, l)) dummy_head = cur_node = ListNode(0) while min_heap: _, node = heapq.heappop(min_heap) # Add this node's value into our result list. cur_node.next = node cur_node = cur_node.next # If there are more elements on current linked-list, # push them back onto the priority queue. if node.next: heapq.heappush(min_heap, (node.next.val, node.next)) return dummy_head.next ``` 该方法的时间复杂度主要取决于构建和维护最小堆的过程,即O(Nlogk),其中N表示所有链表内元素总数目而k代表输入链表的数量。空间复杂度则由用于存储待处理节点的小根堆决定,最坏情况下为O(k)。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值