-
Notifications
You must be signed in to change notification settings - Fork 15
Branch binary search #39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 0 additions & 3 deletions
3
out/production/src/src/algorithms/sorting/insertionSort/README.md
This file was deleted.
Oops, something went wrong.
7 changes: 0 additions & 7 deletions
7
out/production/src/src/dataStructures/disjointSet/quickFind/quick_find.iml
This file was deleted.
Oops, something went wrong.
This file contains hidden or 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,49 @@ | ||
package src.algorithms.searches.binarySearch; | ||
|
||
/** Here, we are implementing BinarySearch where we search an array for a target value at O(log n) time complexity. | ||
* | ||
* Assumptions: | ||
* The array is sorted in ascending order. | ||
* All elements in the array are unique. (to allow for easy testing) | ||
* | ||
* Brief Description and Implementation Invariant: | ||
* With the assumption that the array is sorted in ascending order, BinarySearch reduces the search range by half or | ||
* half + 1 (due to floor division) after every loop. This is done by reassigning the max (high) or min (low) of the | ||
* search range to the middle of the search range when the target value is smaller than or larger than the current | ||
* middle value respectively, and continuing the search thereafter. | ||
* | ||
* In both scenarios where the target is not equal to arr[mid], the high and low pointers are reassigned mid decremented | ||
* /incremented by 1. This ensures that there will never be an infinite loop as the search range will no longer include | ||
* the mid-value, causing the search range to constantly "shrink". We know we can decrement/increment mid by 1 during | ||
* the reassignment as the mid-value is definitely not the target and should no longer be in the search range. | ||
* | ||
* At the end of every loop, we know that the target value is either within the search range or does not exist in the | ||
* array, thereby ensuring the correctness of the algorithm. | ||
* | ||
* Since after each iteration, the search range is halved, it will only take a maximum of O(log n) times before the | ||
* target is either found or determined to not exist in the array. | ||
*/ | ||
public class BinarySearch { | ||
/** | ||
* Searches for a target value within a sorted array using the binary search algorithm. | ||
* @param arr the sorted array in which the search is to be performed. | ||
* @param target the value to be searched for. | ||
* @return the index of the target if found, otherwise -1. | ||
*/ | ||
public static int search(int[] arr, int target) { | ||
int high = arr.length - 1; // max index is 3 if array length is 4 | ||
int low = 0; | ||
while (low <= high) { // When low == high, arr[low] can still == target, therefore should still check | ||
int mid = low + (high - low) / 2; // equivalent to high + low / 2 but reduces cases of integer overflow | ||
if (arr[mid] > target) { | ||
high = mid - 1; // -1 since current mid is not == target and should not be in the search range anymore | ||
} else if (arr[mid] < target) { | ||
low = mid + 1; // +1 since current mid is not == target and should not be in the search range anymore | ||
} else { | ||
return mid; | ||
} | ||
} | ||
|
||
return -1; | ||
} | ||
} |
66 changes: 66 additions & 0 deletions
66
src/algorithms/searches/binarySearch/BinarySearchTemplated.java
This file contains hidden or 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,66 @@ | ||
package src.algorithms.searches.binarySearch; | ||
|
||
/** Here, we are implementing BinarySearchTemplated where we search an array for a target value at O(log n) time | ||
* complexity. | ||
* | ||
* Assumptions: | ||
* The array is sorted in ascending order. | ||
* All elements in the array are unique. (to allow for easy testing) | ||
* | ||
* Brief Description and Implementation Invariant: | ||
* With the assumption that the array is sorted in ascending order, BinarySearchTemplated reduces the search range by | ||
* half or half + 1 (due to floor division) after every loop. This is done by reassigning the max (high) or min (low) of | ||
* the search range to the middle of the search range when the target value is smaller than or larger than the current | ||
* middle value respectively, and continuing the search thereafter. | ||
* | ||
* In this version, there is no condition to check if the current mid is equal to the target to prematurely end the | ||
* search. Hence, the only way for the loop to complete is when low exceeds high. | ||
* | ||
* At the end of every loop, we know that the target value is either within the search range or does not exist in the | ||
* array, thereby ensuring the correctness of the algorithm. | ||
* | ||
* Since after each iteration, the search range is halved, it will only take a maximum of O(log n) times before the | ||
* target is either found or determined to not exist in the array. | ||
*/ | ||
public class BinarySearchTemplated { | ||
/** | ||
* A utility method to compare two integers. | ||
* @param value The current value from the array. | ||
* @param target The value being searched for. | ||
* @return true if the current value is less than the target, otherwise false. | ||
*/ | ||
// The condition should be changed accordingly | ||
public static boolean condition(int value, int target) { | ||
return value >= target; | ||
} | ||
|
||
/** | ||
* Conducts a binary search to find the target within the sorted array. | ||
* | ||
* @param arr The sorted input array. | ||
* @param target The value to be searched within the array. | ||
* @return The index of the target value if found, otherwise -1. | ||
*/ | ||
public static int search(int[] arr, int target) { | ||
// The search space i.e. high and low should be changed accordingly. | ||
int high = arr.length - 1; // max index is 3 if array length is 4 | ||
int low = 0; | ||
while (low < high) { | ||
int mid = low + (high - low) / 2; // equivalent to high + low / 2 but reduces cases of integer overflow | ||
if (condition(arr[mid], target)) { // if value >= target | ||
high = mid; | ||
} else { // if value < target | ||
low = mid + 1; | ||
} | ||
} | ||
|
||
// Checks if low value is indeed the target | ||
// Note that the following checks may not be required in other use cases of this template | ||
if (low < arr.length && arr[low] == target) { | ||
// returned value should be changed accordingly (low or low - 1) | ||
return low; | ||
} | ||
// Returns -1 if loop was exited without finding the target | ||
return -1; | ||
} | ||
} |
This file contains hidden or 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,78 @@ | ||
# Binary Search | ||
Binary search is a search algorithm that finds the position of a target value within a sorted array or list. It compares | ||
the target value to the middle element of the search range, then, based on the comparison, narrows the search to the | ||
upper or lower half of the current search range. | ||
|
||
Two versions of binary search has been implemented in this repository - BinarySearch and BinarySearchTemplated. | ||
|
||
## BinarySearch | ||
 | ||
Image Source: GeeksforGeeks | ||
|
||
BinarySearch is a more straightforward and intuitive version of the binary search algorithm. In this approach, after the | ||
mid-value is calculated, the high and low pointers are adjusted by just one unit. From the above example, after mid | ||
points to index 4 in the first search, the low pointer moves to index 5 (+1) when narrowing the search. Similarly, when | ||
mid points to index 7 in the second search, the high pointer shifts to index 6 (-1) when narrowing the search. This | ||
prevents any possibility of infinite loops. | ||
|
||
## BinarySearchTemplated | ||
|
||
BinarySearchTemplated removes the condition that checks if the current mid-value is equal to the target (which helps to | ||
end the search the moment the target is found). The template adds a "condition" method which will be modified based on | ||
the requirements of the implementation. | ||
|
||
The narrowing of the search space differs from BinarySearch - only one of the high or low pointers will be adjusted by | ||
one unit. | ||
|
||
This template will work for most binary search problems and will only require the following changes: | ||
- Search space (high and low) | ||
- Condition method | ||
- Returned value (low or low - 1) | ||
|
||
### Search Space (Requires change) | ||
Simply modify the initialisation of the high and low pointer according to the search space. | ||
|
||
### Condition (Requires change) | ||
We assume that when the condition returns true, the current value "passes" and when the condition returns false, the | ||
current value "fails". | ||
|
||
In this template, we want to find the first "pass" in the array. | ||
|
||
INSERT IMAGE OF FIRST PASS | ||
|
||
### Returned Value (Requires change) | ||
In the implementation of BinarySearchTemplated, return low was used to find the first "pass". | ||
|
||
EXPLANATION TBC, STILL THINKING HOW TO PHRASE IT. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. LOL ok |
||
|
||
### Search Space Adjustment | ||
What should be the search space adjustment? (Why only low = mid + 1) | ||
|
||
Due to the nature of floor division in Java's \ operator, the searched mid-index will always be smaller than the high | ||
pointer of the previous search range. On the other hand, low = mid + 1, ensures that the searched mid-index is always | ||
larger than the low pointer of the previous search range. This ensures that the search range is narrowed in every loop | ||
and prevents the possibility of infinite loops. | ||
|
||
INSERT IMAGE HERE TO EXPLAIN | ||
|
||
As we close in towards the target value, the final low = mid + 1 narrows the search range from low. TBC ON EXPLANATION | ||
|
||
Credits: [Powerful Ultimate Binary Search Template](https://leetcode.com/discuss/general-discussion/786126/python-powerful-ultimate-binary-search-template-solved-many-problems) | ||
|
||
## Complexity Analysis | ||
**Time**: | ||
- Worst case: O(log n) | ||
- Average case: O(log n) | ||
- Best case: | ||
- BinarySearch O(1) | ||
- BinarySearchTemplated O(log n) | ||
|
||
BinarySearch: | ||
In the worst case, the target is either in the first index or does not exist in the array at all. | ||
In the best case, the target is the middle (odd number of element) or the first middle element (even number of elements) | ||
if floor division is used to determine the middle. | ||
|
||
BinaryTemplated: | ||
In all cases, O(log n) iterations will be required as there is no condition to exit the loop prematurely. | ||
|
||
**Space**: O(1) since no new data structures are used and searching is only done within the array given |
This file contains hidden or 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,51 @@ | ||
package test.algorithms.binarySearchTest; | ||
|
||
import org.junit.Test; | ||
|
||
import src.algorithms.searches.binarySearch.BinarySearchTemplated; | ||
import src.algorithms.searches.binarySearch.BinarySearch; | ||
|
||
import java.util.Arrays; | ||
|
||
import static org.junit.Assert.assertArrayEquals; | ||
import static org.junit.Assert.assertEquals; | ||
|
||
public class BinarySearchTest { | ||
@Test | ||
public void test_binarySearch() { | ||
// Test 1: even number of elements | ||
int[] firstArray = {1, 5, 10, 12}; | ||
int firstResult = BinarySearch.search(firstArray, 1); | ||
|
||
// Test 2: odd number of elements | ||
int[] secondArray = {1, 5, 10, 11, 12}; | ||
int secondResult = BinarySearch.search(secondArray, 11); | ||
|
||
// Test 3: target not in array | ||
int[] thirdArray = {1, 5, 10, 11, 12}; | ||
int thirdResult = BinarySearch.search(thirdArray, 3); | ||
|
||
assertEquals(0, firstResult); | ||
assertEquals(3, secondResult); | ||
assertEquals(-1, thirdResult); | ||
} | ||
|
||
@Test | ||
public void test_binarySearchTemplated() { | ||
// Test 1: even number of elements | ||
int[] firstArray = {1, 5, 10, 12}; | ||
int firstResult = BinarySearchTemplated.search(firstArray, 1); | ||
|
||
// Test 2: odd number of elements | ||
int[] secondArray = {1, 5, 10, 11, 12}; | ||
int secondResult = BinarySearchTemplated.search(secondArray, 11); | ||
|
||
// Test 3: target not in array | ||
int[] thirdArray = {1, 5, 10, 11, 12}; | ||
int thirdResult = BinarySearchTemplated.search(thirdArray, 3); | ||
|
||
assertEquals(0, firstResult); | ||
assertEquals(3, secondResult); | ||
assertEquals(-1, thirdResult); | ||
} | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for the templated version, can also construct ur own problem / source from tutorial qn (this would be best) or give a link to a leetcode BS qn like koko eating bananas