Skip to content

Commit d29afd9

Browse files
committed
Format code using clang-format
1 parent 3eb521b commit d29afd9

File tree

2 files changed

+111
-0
lines changed

2 files changed

+111
-0
lines changed
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package com.thealgorithms.divideandconquer;
2+
3+
/**
4+
* Deterministic QuickSelect (Median of Medians) algorithm.
5+
*
6+
* Finds the kth smallest element in an unsorted array in O(n) worst-case time.
7+
*
8+
* Reference: https://en.wikipedia.org/wiki/Median_of_medians
9+
*/
10+
public final class DeterministicQuickSelect {
11+
12+
private DeterministicQuickSelect() {
13+
}
14+
15+
public static int select(int[] arr, int k) {
16+
if (arr == null) {
17+
throw new IllegalArgumentException("Input array cannot be null");
18+
}
19+
if (k < 1 || k > arr.length) {
20+
throw new IllegalArgumentException("k is out of bounds");
21+
}
22+
return quickSelect(arr, 0, arr.length - 1, k - 1);
23+
}
24+
25+
private static int quickSelect(int[] arr, int left, int right, int k) {
26+
if (left == right) {
27+
return arr[left];
28+
}
29+
30+
int pivotIndex = medianOfMedians(arr, left, right);
31+
pivotIndex = partition(arr, left, right, pivotIndex);
32+
33+
if (k == pivotIndex) {
34+
return arr[k];
35+
} else if (k < pivotIndex) {
36+
return quickSelect(arr, left, pivotIndex - 1, k);
37+
} else {
38+
return quickSelect(arr, pivotIndex + 1, right, k);
39+
}
40+
}
41+
42+
private static int partition(int[] arr, int left, int right, int pivotIndex) {
43+
int pivotValue = arr[pivotIndex];
44+
swap(arr, pivotIndex, right);
45+
int storeIndex = left;
46+
for (int i = left; i < right; i++) {
47+
if (arr[i] < pivotValue) {
48+
swap(arr, storeIndex, i);
49+
storeIndex++;
50+
}
51+
}
52+
swap(arr, right, storeIndex);
53+
return storeIndex;
54+
}
55+
56+
private static int medianOfMedians(int[] arr, int left, int right) {
57+
int n = right - left + 1;
58+
if (n <= 5) {
59+
return partition5(arr, left, right);
60+
}
61+
62+
int numMedians = (int) Math.ceil((double) n / 5);
63+
int[] medians = new int[numMedians];
64+
65+
for (int i = 0; i < numMedians; i++) {
66+
int subLeft = left + i * 5;
67+
int subRight = Math.min(subLeft + 4, right);
68+
medians[i] = arr[partition5(arr, subLeft, subRight)];
69+
}
70+
71+
return quickSelect(medians, 0, medians.length - 1, medians.length / 2);
72+
}
73+
74+
private static int partition5(int[] arr, int left, int right) {
75+
java.util.Arrays.sort(arr, left, right + 1);
76+
return (left + right) / 2;
77+
}
78+
79+
private static void swap(int[] arr, int i, int j) {
80+
int tmp = arr[i];
81+
arr[i] = arr[j];
82+
arr[j] = tmp;
83+
}
84+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.thealgorithms.divideandconquer;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.assertThrows;
5+
6+
import org.junit.jupiter.api.Test;
7+
8+
class DeterministicQuickSelectTest {
9+
10+
@Test
11+
void testSelectKthSmallest() {
12+
int[] arr = {7, 10, 4, 3, 20, 15};
13+
assertEquals(3, DeterministicQuickSelect.select(arr, 1));
14+
assertEquals(4, DeterministicQuickSelect.select(arr, 2));
15+
assertEquals(7, DeterministicQuickSelect.select(arr, 3));
16+
assertEquals(10, DeterministicQuickSelect.select(arr, 4));
17+
assertEquals(15, DeterministicQuickSelect.select(arr, 5));
18+
assertEquals(20, DeterministicQuickSelect.select(arr, 6));
19+
}
20+
21+
@Test
22+
void testInvalidInput() {
23+
assertThrows(IllegalArgumentException.class, () -> DeterministicQuickSelect.select(null, 1));
24+
assertThrows(IllegalArgumentException.class, () -> DeterministicQuickSelect.select(new int[] {1, 2}, 0));
25+
assertThrows(IllegalArgumentException.class, () -> DeterministicQuickSelect.select(new int[] {1, 2}, 3));
26+
}
27+
}

0 commit comments

Comments
 (0)