forked from eugenp/tutorials
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
CS-378 Find kth smallest element in union of two sorted arrays (eugen…
…p#9812) * CS-378 Find the Kth Smallest Element in the Union of Two Sorted Arrays * CS-378 Fix name of unit test * CS-378 Update merge algorithm to operate only on two input arrays Co-authored-by: mikr <[email protected]>
- Loading branch information
Showing
2 changed files
with
414 additions
and
0 deletions.
There are no files selected for viewing
126 changes: 126 additions & 0 deletions
126
algorithms-searching/src/main/java/com/baeldung/algorithms/kthsmallest/KthSmallest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
package com.baeldung.algorithms.kthsmallest; | ||
|
||
import java.util.Arrays; | ||
import java.util.NoSuchElementException; | ||
|
||
import static java.lang.Math.max; | ||
import static java.lang.Math.min; | ||
|
||
public class KthSmallest { | ||
|
||
public static int findKthSmallestElement(int k, int[] list1, int[] list2) throws NoSuchElementException, IllegalArgumentException { | ||
|
||
checkInput(k, list1, list2); | ||
|
||
// we are looking for the minimum value | ||
if(k == 1) { | ||
return min(list1[0], list2[0]); | ||
} | ||
|
||
// we are looking for the maximum value | ||
if(list1.length + list2.length == k) { | ||
return max(list1[list1.length-1], list2[list2.length-1]); | ||
} | ||
|
||
// swap lists if needed to make sure we take at least one element from list1 | ||
if(k <= list2.length && list2[k-1] < list1[0]) { | ||
int[] list1_ = list1; | ||
list1 = list2; | ||
list2 = list1_; | ||
} | ||
|
||
// correct left boundary if k is bigger than the size of list2 | ||
int left = k < list2.length ? 0 : k - list2.length - 1; | ||
|
||
// the inital right boundary cannot exceed the list1 | ||
int right = min(k-1, list1.length - 1); | ||
|
||
int nElementsList1, nElementsList2; | ||
|
||
// binary search | ||
do { | ||
nElementsList1 = ((left + right) / 2) + 1; | ||
nElementsList2 = k - nElementsList1; | ||
|
||
if(nElementsList2 > 0) { | ||
if (list1[nElementsList1 - 1] > list2[nElementsList2 - 1]) { | ||
right = nElementsList1 - 2; | ||
} else { | ||
left = nElementsList1; | ||
} | ||
} | ||
} while(!kthSmallesElementFound(list1, list2, nElementsList1, nElementsList2)); | ||
|
||
return nElementsList2 == 0 ? list1[nElementsList1-1] : max(list1[nElementsList1-1], list2[nElementsList2-1]); | ||
} | ||
|
||
private static boolean kthSmallesElementFound(int[] list1, int[] list2, int nElementsList1, int nElementsList2) { | ||
|
||
// we do not take any element from the second list | ||
if(nElementsList2 < 1) { | ||
return true; | ||
} | ||
|
||
if(list1[nElementsList1-1] == list2[nElementsList2-1]) { | ||
return true; | ||
} | ||
|
||
if(nElementsList1 == list1.length) { | ||
return list1[nElementsList1-1] <= list2[nElementsList2]; | ||
} | ||
|
||
if(nElementsList2 == list2.length) { | ||
return list2[nElementsList2-1] <= list1[nElementsList1]; | ||
} | ||
|
||
return list1[nElementsList1-1] <= list2[nElementsList2] && list2[nElementsList2-1] <= list1[nElementsList1]; | ||
} | ||
|
||
|
||
private static void checkInput(int k, int[] list1, int[] list2) throws NoSuchElementException, IllegalArgumentException { | ||
|
||
if(list1 == null || list2 == null || k < 1) { | ||
throw new IllegalArgumentException(); | ||
} | ||
|
||
if(list1.length == 0 || list2.length == 0) { | ||
throw new IllegalArgumentException(); | ||
} | ||
|
||
if(k > list1.length + list2.length) { | ||
throw new NoSuchElementException(); | ||
} | ||
} | ||
|
||
public static int getKthElementSorted(int[] list1, int[] list2, int k) { | ||
|
||
int length1 = list1.length, length2 = list2.length; | ||
int[] combinedArray = new int[length1 + length2]; | ||
System.arraycopy(list1, 0, combinedArray, 0, list1.length); | ||
System.arraycopy(list2, 0, combinedArray, list1.length, list2.length); | ||
Arrays.sort(combinedArray); | ||
|
||
return combinedArray[k-1]; | ||
} | ||
|
||
public static int getKthElementMerge(int[] list1, int[] list2, int k) { | ||
|
||
int i1 = 0, i2 = 0; | ||
|
||
while(i1 < list1.length && i2 < list2.length && (i1 + i2) < k) { | ||
if(list1[i1] < list2[i2]) { | ||
i1++; | ||
} else { | ||
i2++; | ||
} | ||
} | ||
|
||
if((i1 + i2) < k) { | ||
return i1 < list1.length ? list1[k - i2 - 1] : list2[k - i1 - 1]; | ||
} else if(i1 > 0 && i2 > 0) { | ||
return Math.max(list1[i1-1], list2[i2-1]); | ||
} else { | ||
return i1 == 0 ? list2[i2-1] : list1[i1-1]; | ||
} | ||
} | ||
} |
Oops, something went wrong.