Question 3a Smallest K numbers

The suggested solution mentioned an algorithm which is very similar to my initial thought : heapfy the whole input array into a minimum heap and then popup minimum for k times. To heapfy an array of length n will take O(2n)  (the factor is 2),so this solution will take O(2n + k 2 logn) time. Let's call it option1.

 

My initial thought is to heapfy first k elements into a maximum heap and then compare the top element with each following input element to decide whether to remove and the top and insert the new one(see my previous article). So the time complexity of this solution will be O(2k + (n-k) 2 logk ). Let's call it option2.

 

Suppose k is a certain fixed number , so if only logk > 1 ( k>2) , the option1 should outperform the option2.

 

Java Implementation:

public class KSmallestA {

	public static void main(String[] args) {
		 assertEquals(new int[]{1,2,3,4}, getKSmallest(new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 4));
         assertEquals(new int[]{1,2,3,4}, getKSmallest(new int[]{10, 9, 8, 7, 6, 5, 4, 3, 2, 1}, 4));
         assertEquals(new int[]{21,22,14,18,9}, getKSmallest(new int[]{27, 14, 18, 22, 21, 91, 33, 36, 42, 78 , 9, 65, 101, 29}, 5));
	}
	
	private static void assertEquals(int[] standard, int[] result) {
		Arrays.sort(standard);
		Arrays.sort(result);
		assert Arrays.equals(standard, result);
		
	}

	public static int[] getKSmallest(int[] nums , int k) {
		MinIntHeap heap = new MinIntHeap(nums, 0 , nums.length);
		int[] result = new int[k];
		for (int i = 0 ; i < k ; i ++ ) {
			result[i] = heap.pop();
		}
		
		return result;
	}

}

class MinIntHeap {
		
		private int[] nums;
		private int count;

		
		public MinIntHeap ( int[] nums, int offset, int count){
		   this.nums = new int[count+1]; // index 0 will not be used
		   System.arraycopy(nums, offset, this.nums, 1, count);
		   this.count = count;
		   for ( int i = count/2 ; i > 0 ; i --) {
			   swimDown(i);
		   }
		}
		
		public int[] getAll() {
			int result[] = new int[count];
			System.arraycopy(this.nums, 1, result, 0, count);
			return result;
		}
	    
		
		private void swimUp (int i) {
			int parent = i/2;
			while (parent != 0 && nums[i] < nums[parent]) {
				swap ( i, parent);
				i = parent;
				parent = i/2;
			}
		}
		
		private void swimDown(int i) {
			int lchild = i * 2;
			if ( lchild > count )
				return;
			int smaller = lchild;
			int rchild = lchild + 1;
			if (rchild <= count && nums[rchild] < nums[lchild]) 
				smaller = rchild; 
			while( nums[smaller] < nums[i]) {
				swap ( smaller, i);
				i = smaller;
				lchild = i * 2;
				if ( lchild > count )
					return;
				smaller = lchild;
				rchild = lchild + 1;
				if (rchild <= count && nums[rchild] < nums[lchild]) 
					smaller = rchild; 
			}
			
		}
		
		private void swap (int i , int j) {
			int temp = nums[i];
			nums[i] = nums[j];
			nums[j] = temp;
		}
		
		public int peek() {
			return nums[1];
		}
		
		public int pop() {
			swap(1, count--);
			swimDown(1);
			return nums[count + 1];
		}
		
		//don't concern resizing array here
		public void add (int num) {
			nums[++count] = num;
			swimUp(count);
		}
	}

 

你可能感兴趣的:(minimum heap,k smallest)