Merge k Sorted Lists 合并k个有序链表@LeetCode

还是基于merge的思想

方法1:
依次取每个数组的首个元素进行比较,pop出最大者放入结果数组,直到所有数据处理完毕。这个做法每得到一个结果就需要比较K次。

package Level3;

import java.util.ArrayList;

import Utility.ListNode;

/**
 * Merge k Sorted Lists 
 * Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
 * 
 */
public class S23 {

	public static void main(String[] args) {
		int[] a = {1,2,3};
		ListNode aLN = ListNode.create(a);
		ArrayList<ListNode> lists = new ArrayList<ListNode>();
		lists.add(aLN);
		ListNode h = mergeKLists(lists);
		h.print();
	}
	
	public static ListNode mergeKLists(ArrayList<ListNode> lists) {
		ListNode mergedHead = new ListNode(-1);		// 利用dummy作为表头
		ListNode[] ptrs = new ListNode[lists.size()];		// 指针指向每一个ListNode
		
		for(int i=0; i<lists.size(); i++){		// 初始化指针数组
			ptrs[i] = lists.get(i);
		}
		
		ListNode mergedCur = mergedHead;
		boolean run = true;
		while(true){
			run = false;			// run用来检测是否所有的链表都已经遍历完了,即指针为null
			int val = Integer.MAX_VALUE;
			int minIndex = 0;
			for(int j=0; j<ptrs.length; j++){		// 找到最小的那一个表头
				if(ptrs[j] != null){
					run = true;
					if(ptrs[j].val < val){
						val = ptrs[j].val;
						minIndex = j;
					}
				}
			}
			if(!run){			// 及时退出
				break;
			}
			mergedCur.next = new ListNode(ptrs[minIndex].val);	// 更新merged链表和最小的表头指针
			ptrs[minIndex] = ptrs[minIndex].next;
			mergedCur = mergedCur.next;
		}
		
		return mergedHead.next;
    }

}

这道题有更快的利用堆的多路归并做法:

方法2:

建立含有K个元素的最大堆,堆的初值分别来自K个数组的首个元素。堆的每个结点同时记录了如下信息:1) 该结点的取值;2) 来自哪个数组;3) 该取值位于数组中的位置。
每次pop出最大堆的堆顶(pop出后要调整保持最大堆),加入结果数组。同时可以知道该元素的所在数组以及位置,把其在数组中下一个位置的元素insert进最大堆。直到所有数据处理完毕。
pop出堆顶的最坏情况复杂度是log(K),insert一个元素进最大堆的最坏情况复杂度是log(K),因此每得到一个结果在最坏情况下需要比较2logK次



用递归做会TLE,所以第二遍还是用迭代法做

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode mergeKLists(List<ListNode> lists) {
		if (lists.size() == 0) {
			return null;
		}
		ListNode merged = new ListNode(0);
		ListNode cur = merged;
		
		ListNode[] ptrs = new ListNode[lists.size()];
		for(int i=0; i<lists.size(); i++) {
		    ptrs[i] = lists.get(i);
		}

		while(true) {
		    int minIndex = -1;
		    int min = Integer.MAX_VALUE;
		    for(int i=0; i<ptrs.length; i++) {
		        if(ptrs[i] != null && ptrs[i].val < min) {
		            min = ptrs[i].val;
		            minIndex = i;
		        }
		    }
		    if(minIndex == -1) {
		        break;
		    }
		    cur.next = new ListNode(min);
		    ptrs[minIndex] = ptrs[minIndex].next;
		    cur = cur.next;
		}
		
		return merged.next;
    }
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值