diff --git a/src/main/java/com/bl/binary_search/README.md b/src/main/java/com/bl/binary_search/README.md new file mode 100644 index 0000000..38cc659 --- /dev/null +++ b/src/main/java/com/bl/binary_search/README.md @@ -0,0 +1,32 @@ +# 704. Binary Search + +Difficulty: `Easy` +Topics: `Array`, `Binary Search` + +Given an array of integers `nums` which is sorted in ascending order, and an integer `target`, write a function to +search `target` in `nums`. If `target` exists, then return its index. Otherwise, return `-1`. + +You must write an algorithm with `O(log n)` runtime complexity. + +**Example 1:** + +```text +Input: nums = [-1,0,3,5,9,12], target = 9 +Output: 4 +Explanation: 9 exists in nums and its index is 4 +``` + +**Example 2:** + +```text +Input: nums = [-1,0,3,5,9,12], target = 2 +Output: -1 +Explanation: 2 does not exist in nums so return -1 +``` + +**Constraints:** + +- `1 <= nums.length <= 10^4` +- `-10^4 < nums[i], target < 10^4` +- All the integers in `nums` are unique. +- `nums` is sorted in ascending order. \ No newline at end of file diff --git a/src/main/java/com/bl/binary_search/Solution.java b/src/main/java/com/bl/binary_search/Solution.java new file mode 100644 index 0000000..c3f5ec6 --- /dev/null +++ b/src/main/java/com/bl/binary_search/Solution.java @@ -0,0 +1,44 @@ +package com.bl.binary_search; + +/** + * This is the solution to the LeetCode problem: 704. Binary Search + * + * @author Børre A. Opedal Lunde + * @since 2024.01.27 + */ +public class Solution { + + public int search(int[] nums, int target) { + + int low = 0; + int high = nums.length - 1; + + // The loop will continue until the target is found or the low and high + // indices have crossed each other. In which the target was not found. + while (low <= high) { + + // The reason why we don't use (low + high) / 2 is because it can + // cause an integer overflow. For example: + // low = 2 000 000 000 + // high = 2 000 000 000 + // low + high = 4 000 000 000 which is larger than the maximum + // integer value: 2 147 483 647 + final int middleIndex = low + (high - low) / 2; + final int middleValue = nums[middleIndex]; + + if (middleValue == target) { + // The target was found, return its index. + return middleIndex; + } else if (middleValue > target) { + // The target must be in the left half (lower half) of the array. + high = middleIndex - 1; + } else { + // The target must be in the right half (upper half) of the array. + low = middleIndex + 1; + } + } + + // -1 represents that the target was not found. + return - 1; + } +} diff --git a/src/test/java/com/bl/binary_search/SolutionTest.java b/src/test/java/com/bl/binary_search/SolutionTest.java new file mode 100644 index 0000000..3dc3c78 --- /dev/null +++ b/src/test/java/com/bl/binary_search/SolutionTest.java @@ -0,0 +1,103 @@ +package com.bl.binary_search; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * This is the test to the LeetCode problem: 704. Binary Search + * + * @author Børre A. Opedal Lunde + * @since 2024.01.27 + */ +@DisplayName("Binary Search") +class SolutionTest { + + private final Solution solution = new Solution(); + + @Test + @DisplayName("Example one") + void exampleOne() { + int[] nums = {- 1, 0, 3, 5, 9, 12}; + int target = 9; + + int expected = 4; + int actual = solution.search(nums, target); + + assertEquals(expected, actual); + } + + @Test + @DisplayName("Example two") + void exampleTwo() { + int[] nums = {- 1, 0, 3, 5, 9, 12}; + int target = 2; + + int expected = - 1; + int actual = solution.search(nums, target); + + assertEquals(expected, actual); + } + + @Test + @DisplayName("Empty array should return -1") + void emptyArrayShouldReturn1() { + int[] nums = {}; + int target = 9; // Doesn't matter what the target is. + + int expected = - 1; + int actual = solution.search(nums, target); + + assertEquals(expected, actual); + } + + @Test + @DisplayName("Target is a negative number") + void targetIsANegativeNumber() { + int[] nums = {- 1, 0, 3, 5, 9, 12}; + int target = - 1; + + int expected = 0; + int actual = solution.search(nums, target); + + assertEquals(expected, actual); + } + + @Test + @DisplayName("Target is larger than the largest number in the array") + void targetIsLargerThanTheLargestNumberInTheArray() { + int[] nums = {- 1, 0, 3, 5, 9, 12}; + int target = 13; + + int expected = - 1; + int actual = solution.search(nums, target); + + assertEquals(expected, actual); + } + + @Test + @DisplayName("Target is smaller than the smallest number in the array") + void targetIsSmallerThanTheSmallestNumberInTheArray() { + int[] nums = {- 1, 0, 3, 5, 9, 12}; + int target = - 2; + + int expected = - 1; + int actual = solution.search(nums, target); + + assertEquals(expected, actual); + } + + @Test + @DisplayName("All elements in the array are the same") + void allElementsInTheArrayAreTheSame() { + int[] nums = {1, 1, 1, 1, 1, 1}; + int target = 1; + + int actual = solution.search(nums, target); + + // The actual index is not important, as long as it's a valid index. + assertTrue(actual >= 0 && nums[actual] == target); + } +} \ No newline at end of file