package com.interview.array;
/**
* http://stackoverflow.com/questions/4686823/given-2-sorted-arrays-of-integers-find-the-nth-largest-number-in-sublinear-time
* http://articles.leetcode.com/2011/01/find-k-th-smallest-element-in-union-of.html
*/
public class KthLargestInTwoSortedArray {
public int kthLargest1(int arr1[],int arr2[],int low1,int high1,int low2,int high2,int k){
int len1 = high1-low1 +1;
int len2 = high2 - low2+1;
if(len1 == 0){
return arr2[low2+k];
}
if(len2 ==0){
return arr1[low1+k];
}
if(k == 0){
return Math.min(arr1[low1], arr2[low2]);
}
int mid1 = len1*k/(len1 + len2);
int mid2 = k - mid1 - 1;
mid1 = low1+mid1;
mid2 = low2 + mid2;
if(arr1[mid1] > arr2[mid2]){
k = k - mid2 + low2 -1;
high1 = mid1;
low2 = mid2 + 1;
}else{
k = k - mid1 + low1 -1;
high2 = mid2;
low1 = mid1+1;
}
return kthLargest(arr1, arr2, low1, high1, low2, high2, k);
}
public int kthLargest(int input1[],int input2[],int k){
return kthLargest(input1, input2, 0, input1.length-1, 0, input2.length-1, k);
}
private int kthLargest(int input1[],int input2[],int l1, int h1, int l2,int h2,int k){
if(l1 > h1){
return input2[k-1];
}
if(l2 > h2){
return input1[k-1];
}
if((h1 - l1 + 1) + (h2 - l2 + 1) == k){
return Math.max(input1[h1], input2[h2]);
}
if(k == 1){
return Math.min(input1[l1],input2[l2]);
}
//handle the situation where only one element is left
//in either of array.
//e.g k =2 and arr1 = 8 arr2 = 1,9,11
//we try to find if 8 is before 9 betweenn 1 and 9
//or before 1. In all these cases k will be either
//1 8 or 9
if(l2 == h2 || l1 == h1){
if(l2 == h2){
if(input1[l1+k-1] < input2[l2]){
return input1[l1+k-1];
}else if(input1[l1+k-2] > input2[l2]){
return input1[l1+k-2];
}else{
return input2[l2];
}
}
if(l1 == h1){
if(input2[l2+k-1] < input1[l1]){
return input2[l2+k-1];
}else if(input2[l2+k-2] > input1[l1]){
return input2[l2+k-2];
}else{
return input1[l1];
}
}
}
int m1 = (h1 + l1)/2;
int m2 = (h2 + l2)/2;
int diff1 = m1 - l1+1;
int diff2 = m2 - l2+1;
if(diff1 + diff2 >= k){
if(input1[m1] < input2[m2]){
return kthLargest(input1, input2, l1, h1, l2, m2, k);
}else{
return kthLargest(input1, input2, l1, m1, l2, h2, k);
}
}else{
if(input1[m1] < input2[m2]){
return kthLargest(input1, input2,m1+1, h1, l2, h2, k - diff1);
}else{
return kthLargest(input1, input2, l1, h1, m2+1, h2, k -diff2);
}
}
}
public static void main(String args[]){
KthLargestInTwoSortedArray kis = new KthLargestInTwoSortedArray();
int input1[] = {1,4,7,11,17,21};
int input2[] = {-4,-1,3,4,6,28,35,41,56,70};
for(int i = 0; i < input1.length + input2.length; i++){
System.out.println(kis.kthLargest(input1, input2, i+1));
}
// System.out.println(kis.kthLargest(input1, input2, 6));
}
}