O(N lgK) 时间内合并K个有序链表

问题:

在O(N lgK) 时间内合并K个有序链表, 这里N指的是K个链表中所有的元素个数。

分析:

这是一道非常经典的面试题,在很多大公司的面试题中,此题频繁出现。这题也是算法导论的作业题。

这题的思路如下:

1) 在每一个链表中取出第一个值,然后把它们放在一个大小为K的数组里,然后把这个数组当成heap,然后把该堆建成最小堆。此步骤的时间复杂度为O(K)

2 )取出堆中的最小值(也是数组的第一个值),然后把该最小值所处的链表的下一个值放在数组的第一个位置。如果链表中有一个已经为空(元素已经都被取出),则改变heap的大小。然后,执行MIN-HEAPIFY操作,此步骤的时间复杂度为O(lg K).

3 ) 不断的重复步骤二,直到所有的链表都为空。

代码如下:

	public void minHeapify(Node[] node, int index, int size) {
		int left = 2 * index + 1;
		int right = 2 * index + 2;
		int smallest;
		
		if (left < size && node[left].data < node[index].data) {
			smallest = left;
		} else {
			smallest = index;
		}
		
		if (right < size && node[right].data < node[smallest].data) {
			smallest = right;
		}
		
		if (smallest != index) {
			exchange(node, smallest, index);
			minHeapify(node, smallest, size);
		}
	}
创建最小堆:

	public void buildMinHeap(Node[] node, int size) {
		for (int i = size / 2 - 1; i >= 0; i--) {
			minHeapify(node, i, size);
		}
	}
合并:

public Node mergeKSortedList(Node[] heads) {
		Node head = null; // the head of the merged list
		Node current = null;
		int size = heads.length;
		Node[] heap = new Node[heads.length]; // create a heap
		// initialize the value of the heap
		for (int i = 0; i < heads.length; i++) {
			heap[i] = heads[i];
			heads[i] = heads[i].next;
		}
		// create a min heap
		buildMinHeap(heap, size);
		
		int tempSize = size;
		while (size > 0) {
			if (head == null) {
				head = heap[0];
				current = head;
			} else {
				current.next = heap[0];
				current = current.next;
			}
			if (heap[0].next == null) {
				size--;
			} else {
				heap[0] = heap[0].next;
			}
			
			// if the size of heap changes, we need to move all the elements in the heap to
			// the front of the heap
			if (size != tempSize) {
				for (int i = 0; i < size; i++) {
					heap[i] = heap[i+1];
				}
				tempSize = size;
			}
			minHeapify(heap, 0, size);
		}
		return head;
	}

主文件:

public static void main(String[] args) {
		
		int k = 3;
		Node[] heads = new Node[k];
		
		Node n1 = new Node(1);
		Node n7 = new Node(7);
		Node n9 = new Node(9);
		Node n2 = new Node(2);
		Node n4 = new Node(4);
		Node n8 = new Node(8);
		Node n3 = new Node(3);
		Node n5 = new Node(5);
		Node n6 = new Node(6);
		
		n1.next = n7;
		n7.next = n9;
		n2.next = n4;
		n4.next = n8;
		n3.next = n5;
		n5.next = n6;
		
		heads[0] = n1;
		heads[1] = n2;
		heads[2] = n3;
		
		Test test = new Test();
		Node head = test.mergeKSortedList(heads);
		while(head != null) {
			System.out.println(head.data);
			head = head.next;
		}
		
	}

转载请注明出处:http://blog.csdn.net/beiyeqingteng



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值