Skip to content

Commit 5b6c1fa

Browse files
Maiklinsmikr
andauthored
CS-378 Find kth smallest element in union of two sorted arrays (eugenp#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 <michael.krimgen@ximedes.com>
1 parent 20c14c7 commit 5b6c1fa

2 files changed

Lines changed: 414 additions & 0 deletions

File tree

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
package com.baeldung.algorithms.kthsmallest;
2+
3+
import java.util.Arrays;
4+
import java.util.NoSuchElementException;
5+
6+
import static java.lang.Math.max;
7+
import static java.lang.Math.min;
8+
9+
public class KthSmallest {
10+
11+
public static int findKthSmallestElement(int k, int[] list1, int[] list2) throws NoSuchElementException, IllegalArgumentException {
12+
13+
checkInput(k, list1, list2);
14+
15+
// we are looking for the minimum value
16+
if(k == 1) {
17+
return min(list1[0], list2[0]);
18+
}
19+
20+
// we are looking for the maximum value
21+
if(list1.length + list2.length == k) {
22+
return max(list1[list1.length-1], list2[list2.length-1]);
23+
}
24+
25+
// swap lists if needed to make sure we take at least one element from list1
26+
if(k <= list2.length && list2[k-1] < list1[0]) {
27+
int[] list1_ = list1;
28+
list1 = list2;
29+
list2 = list1_;
30+
}
31+
32+
// correct left boundary if k is bigger than the size of list2
33+
int left = k < list2.length ? 0 : k - list2.length - 1;
34+
35+
// the inital right boundary cannot exceed the list1
36+
int right = min(k-1, list1.length - 1);
37+
38+
int nElementsList1, nElementsList2;
39+
40+
// binary search
41+
do {
42+
nElementsList1 = ((left + right) / 2) + 1;
43+
nElementsList2 = k - nElementsList1;
44+
45+
if(nElementsList2 > 0) {
46+
if (list1[nElementsList1 - 1] > list2[nElementsList2 - 1]) {
47+
right = nElementsList1 - 2;
48+
} else {
49+
left = nElementsList1;
50+
}
51+
}
52+
} while(!kthSmallesElementFound(list1, list2, nElementsList1, nElementsList2));
53+
54+
return nElementsList2 == 0 ? list1[nElementsList1-1] : max(list1[nElementsList1-1], list2[nElementsList2-1]);
55+
}
56+
57+
private static boolean kthSmallesElementFound(int[] list1, int[] list2, int nElementsList1, int nElementsList2) {
58+
59+
// we do not take any element from the second list
60+
if(nElementsList2 < 1) {
61+
return true;
62+
}
63+
64+
if(list1[nElementsList1-1] == list2[nElementsList2-1]) {
65+
return true;
66+
}
67+
68+
if(nElementsList1 == list1.length) {
69+
return list1[nElementsList1-1] <= list2[nElementsList2];
70+
}
71+
72+
if(nElementsList2 == list2.length) {
73+
return list2[nElementsList2-1] <= list1[nElementsList1];
74+
}
75+
76+
return list1[nElementsList1-1] <= list2[nElementsList2] && list2[nElementsList2-1] <= list1[nElementsList1];
77+
}
78+
79+
80+
private static void checkInput(int k, int[] list1, int[] list2) throws NoSuchElementException, IllegalArgumentException {
81+
82+
if(list1 == null || list2 == null || k < 1) {
83+
throw new IllegalArgumentException();
84+
}
85+
86+
if(list1.length == 0 || list2.length == 0) {
87+
throw new IllegalArgumentException();
88+
}
89+
90+
if(k > list1.length + list2.length) {
91+
throw new NoSuchElementException();
92+
}
93+
}
94+
95+
public static int getKthElementSorted(int[] list1, int[] list2, int k) {
96+
97+
int length1 = list1.length, length2 = list2.length;
98+
int[] combinedArray = new int[length1 + length2];
99+
System.arraycopy(list1, 0, combinedArray, 0, list1.length);
100+
System.arraycopy(list2, 0, combinedArray, list1.length, list2.length);
101+
Arrays.sort(combinedArray);
102+
103+
return combinedArray[k-1];
104+
}
105+
106+
public static int getKthElementMerge(int[] list1, int[] list2, int k) {
107+
108+
int i1 = 0, i2 = 0;
109+
110+
while(i1 < list1.length && i2 < list2.length && (i1 + i2) < k) {
111+
if(list1[i1] < list2[i2]) {
112+
i1++;
113+
} else {
114+
i2++;
115+
}
116+
}
117+
118+
if((i1 + i2) < k) {
119+
return i1 < list1.length ? list1[k - i2 - 1] : list2[k - i1 - 1];
120+
} else if(i1 > 0 && i2 > 0) {
121+
return Math.max(list1[i1-1], list2[i2-1]);
122+
} else {
123+
return i1 == 0 ? list2[i2-1] : list1[i1-1];
124+
}
125+
}
126+
}

0 commit comments

Comments
 (0)