Skip to content

Commit d0662d5

Browse files
authored
Merge pull request #86 from jaebradley/implement-binary-search
Implement binary search
2 parents 208bad7 + 9fd7759 commit d0662d5

File tree

3 files changed

+150
-0
lines changed

3 files changed

+150
-0
lines changed

codereview/binarySearch.md

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
## Purpose
2+
3+
Implement a binary search algorithm that takes a sorted `int` array and some `int` target value and returns the index of the
4+
target value, if it exists.
5+
6+
## Discussion
7+
8+
The way I thought about implementing a binary search algorithm was the following
9+
10+
1. Given an array of sorted `int` values, pick the first, last, and middle indices (round down if there is an even number of indices).
11+
2. If the target value equals any of the values at the first/ last / middle index, return that index.
12+
Else, check to see if the target value is less / greater than the middle index value.
13+
1. If it's less than the middle index value, than we can assume that the target value, if it exists,
14+
is between the first index and the middle index (since the array should be sorted). Thus, we can call our search
15+
function on this sub-array, specifying a start index of the first index + 1 (since we already checked this)
16+
and an end index of the middle index - 1 (again, since we already checked this).
17+
2. If it's greater than the middle index value, we can assume that the target value is between the middle index and the last index.
18+
Thus, we can call the search function on this sub-array, specifying a start index of the middle index + 1 and an
19+
end index of the last index - 1.
20+
3. We continue this process of analyzing the sub-arrays until our sub-array is empty, in which case a `NoSuchElementException`
21+
is thrown.
22+
23+
24+
Things that I'm unsure about
25+
26+
* Does it make sense to have the `public` `search` method immediately call the `private` `searchSubArray` method?
27+
The reason I did this is to obfuscate the idea of a `leftIndex` / `rightIndex` from the API user.
28+
* Does the `NoSuchElementException` make sense? Would returning `-1` make more sense?
29+
* Any particular thoughts on my use of early returns?
30+
31+
## Implementation
32+
33+
import java.util.NoSuchElementException;
34+
35+
public class BinarySearcher {
36+
/**
37+
* Executes a binary search for some target value given an input array of sorted values
38+
* @param values a sorted array
39+
* @param target a value to search for
40+
* @return the index of the target value, if it exists. If the target value does not exist, a NoSuchElementException is thrown.
41+
*/
42+
public static int search(int[] values, int target) {
43+
return searchSubArray(values, 0, values.length - 1, target);
44+
}
45+
46+
private static int searchSubArray(int[] values, int leftIndex, int rightIndex, int target) {
47+
if (values.length == 0 || leftIndex < 0 || rightIndex < 0) {
48+
throw new NoSuchElementException(String.format("Unable to find target: {} in values", target));
49+
}
50+
51+
if (target == values[leftIndex]) {
52+
return leftIndex;
53+
}
54+
55+
if (target == values[rightIndex]) {
56+
return rightIndex;
57+
}
58+
59+
int middleIndex = Double.valueOf(Math.floor((rightIndex - leftIndex) / 2)).intValue();
60+
61+
int middleValue = values[middleIndex];
62+
63+
if (target < middleValue) {
64+
return searchSubArray(values, leftIndex + 1, middleIndex - 1, target);
65+
}
66+
67+
else if (target > middleValue) {
68+
return searchSubArray(values, middleIndex + 1, rightIndex - 1, target);
69+
}
70+
71+
else {
72+
return middleIndex;
73+
}
74+
}
75+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package problems.impl;
2+
3+
import java.util.NoSuchElementException;
4+
5+
public class BinarySearcher {
6+
/**
7+
* Executes a binary search for some target value given an input array of sorted values
8+
* @param values a sorted array
9+
* @param target a value to search for
10+
* @return the index of the target value, if it exists. If the target value does not exist, a NoSuchElementException is thrown.
11+
*/
12+
public static int search(int[] values, int target) {
13+
if (values.length == 0) {
14+
throw new NoSuchElementException(String.format("Unable to find target: {} in values", target));
15+
}
16+
17+
int leftIndex = 0;
18+
int rightIndex = values.length - 1;
19+
while (leftIndex < rightIndex) {
20+
int middleIndex = leftIndex + (rightIndex - leftIndex) / 2;
21+
int middleValue = values[middleIndex];
22+
23+
if (target < middleValue) {
24+
rightIndex = middleIndex;
25+
} else if (target > middleValue) {
26+
leftIndex = middleIndex + 1;
27+
} else {
28+
return middleIndex;
29+
}
30+
}
31+
32+
return leftIndex;
33+
}
34+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package problems.impl;
2+
3+
import org.junit.Test;
4+
5+
import java.util.NoSuchElementException;
6+
7+
import static org.junit.Assert.*;
8+
9+
public class BinarySearcherTest {
10+
private final int[] values = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
11+
12+
@Test
13+
public void itShouldFindElements() {
14+
for (int value : values) {
15+
assertEquals(value - 1, BinarySearcher.search(values, value));
16+
}
17+
}
18+
19+
@Test
20+
public void itShouldThrowForAnEmptyArray() {
21+
try {
22+
BinarySearcher.search(new int[] {}, 1);
23+
} catch (NoSuchElementException e) {
24+
// expected
25+
}
26+
}
27+
28+
@Test
29+
public void itShouldThrowSinceItCannotFindElement() {
30+
try {
31+
BinarySearcher.search(values, -1);
32+
} catch (NoSuchElementException e) {
33+
// expected
34+
}
35+
}
36+
37+
@Test
38+
public void itShouldFindElementInSingleElementArray() {
39+
assertEquals(0, BinarySearcher.search(new int[] { 10 }, 10));
40+
}
41+
}

0 commit comments

Comments
 (0)