Reputation: 4578
I am attempting to write a "binary search" which I've never done before. The code below does not work when the value searched for is 6 or 2 and I want to know what I am doing wrong and how to remedy it.
EDIT
To explain what it is suppose to do (based on my understanding) a binary search requires that an array is already sorted, it then looks for the mid-point index of an array. For example, if an array had nine indexes (0-8)the the mid point would be index 4.
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
The algorithm then determines if that mid point has a higher or lower value than the number you are searching for. All elements on the side of the array that does not contain the searched for number and that exist before the midpoint value simply get removed. If the search for value is 8 then the result would be:
[ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
array midpoint value: 5
[ 5, 6, 7, 8, 9 ]
array midpoint value: 7
[ 7, 8, 9 ]
array midpoint value: 8
Code
//_________________________________________________BEGIN notes
// Step 1. Get length of array
// Step 2. Find mid point
// Step 3. Compare if mid point is lower or higher than searched number
// Step 4. lop off unneeded side
// Step 5. go to step 1
//_________________________________________________END notes
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 44, 55];
function getMidPoint(arr, searchNumb) {
var length = arr.length;
var midPoint = Math.floor(length / 2);
var newArr = arr;
console.log(arr);
console.log("array midpoint value: " + arr[midPoint]);
if (arr[midPoint] > searchNumb) {
var newArr = arr.slice(0, arr[midPoint]);
return getMidPoint(newArr, searchNumb);
} else if (arr[midPoint] < searchNumb) {
var newArr = arr.slice(midPoint, arr.length);
return getMidPoint(newArr, searchNumb);
} else {
return arr
}
}
Upvotes: 2
Views: 13859
Reputation: 1
In TypeScript:
const RecursiveBinarySearch = (list: number[], target: number): boolean => {
if (!list) {
return false;
}
let midpoint: number = Math.floor(list.length / 2);
if (list[midpoint] === target) {
return true;
} else if (target > list[midpoint]) {
return RecursiveBinarySearch(list.slice(midpoint + 1, list.length), target)
} else if (target < list[midpoint]) {
return RecursiveBinarySearch(list.slice(0, midpoint), target)
} else {
return false;
}
}
const verify = (result: boolean): boolean => {
return result;
}
const result:boolean = RecursiveBinarySearch([1,2,3,4,5,6], 6);
const result2: boolean = RecursiveBinarySearch([1,2,3,4,5,6], 9);
console.log(verify(result));
console.log(verify(result2));
Upvotes: 0
Reputation: 11
This is the most comprehensive version of binary recursive search for JavaScript. In my opinion, this is O(log n).
function binaryRecursion(arr, val) {
if (arr.length === 0) return -1
let middle = Math.floor(arr.length - 1 / 2)
if (arr[middle] === val) return middle;
if (val > arr[middle]) {
return binaryRecursion(arr.slice(middle + 1), val)
}
if (val < arr[middle]) {
return binaryRecursion(arr.slice(0, middle), val)
}
}
This returns the index of the element, not whether it exists or not.
Upvotes: 1
Reputation: 1
this too late but i hope this well be useful for some one :)
const items = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
let target = 30;
function binarySearch(L,R){
if(L == R){
return false;
}
let mid = Math.floor((L + R)/2);
if(mid == target){
return target;
}
if(mid > target){
binarySearch(L,mid);
}
if(mid < target){
binarySearch(mid+1,R);
}
}
binarySearch(1,items.length);
Upvotes: 0
Reputation: 401
For a recursive binary search you can try this :
function recursiveBinarySearch(lst, target, start=0, end=(lst.length-1)){
let midPoint = (Math.floor((start+end)/2));
if (start > end){
return false;
}
if (lst[midPoint] === target){
return true;
}
else{
if(lst[midPoint] < target){
return recursiveBinarySearch(lst, target, midPoint+1, end);
}
else{
return recursiveBinarySearch(lst, target, start, midPoint-1);
}
}
}
Upvotes: 0
Reputation: 1
function binarySearch(arr, n) {
let mid = Math.floor(arr.length / 2);
// Base case
if (n === arr[mid]) {
return mid;
}
//Recursion
if (n > arr[mid]) {
return mid + binarySearch(arr.slice(mid, arr.length), n)
} else {
return binarySearch(arr.slice(0, mid), n)
} }
Simple solution to recursive binary search
Upvotes: 0
Reputation: 21
BinarySearch recursion Returning search element index. Below code worked for me
function binerySearchRecursive(arr, num, start=0 end=arr.length-1){
let mid = Math.floor((start+end/2));
if(start> end){
return -1; // edge case if array has 1 element or 0
}
if(num === arr[mid])
return mid;
else if(num < arr[mid])
return binerySearchRecursive(arr, num, start, mid-1 );
else
return binerySearchRecursive(arr, num, mid+1 , end);
}
binerySearchRecursive([1,2,3,4,5], 5)
Upvotes: 0
Reputation: 127
For solving the question in recursion please find the answer and explanation below.
const BinarySearchRec = (arr, el) => {
// finding the middle index
const mid = Math.floor(arr.length / 2);
if (arr[mid] === el) {
// if the element is found then return the element.
return mid;
}
if (arr[mid] < el && mid < arr.length) {
/** here we are having the value returned from recursion as
the value can be -1 as well as a value which is in second half of the original array.**/
const retVal = BinarySearchRec(arr.slice(mid + 1, arr.length), el);
/** if value is greater than or equal to 0 then only add that value with mid
and also one as mid represents the index.
Since index starts from 0 we have to compensate it as we require the length here.**/
return retVal >= 0 ? mid + 1 + retVal : -1;
}
if (arr[mid] > el) {
// here we need not do any manipulation
return BinarySearchRec(arr.slice(0, mid), el);
}
return -1;
};
The above solutions which have been added and the one accepted fails in scenarios when the element to be found is in the second half.
There is solution with while loop which works correctly but since the question was to solve it recursively I have given a comprehensive recursive version.
Upvotes: 1
Reputation: 11
Probably You are already a master with Binary search. However I would like to indicate that is not necessary to create a sliding window for resolving a binary search.
function binarySearch(arr, value){
if(!arr.length) return -1;
let average = Math.floor(arr.length-1/2);
if (value === arr[average]) return average;
if (value > arr[average]) return binarySearch(arr.slice(average+1),value);
if (value < arr[average]) return binarySearch(arr.slice(0,average),value);
}
binarySearch([1,2,3,4,5],6) //-1
binarySearch([1,2,3,4,5],3) //2
Follow this steps to create the Binary search with recursion:
function binarySearch(arr, value){
1 ) implement a base case
if(!arr.length) return -1;
2 ) create a middle point
let average = Math.floor(arr.length-1/2);
3 ) if the middle point is equal to the searched valued, you found it! return the value
if (value === arr[average]) return average;
4) if the value is greater than the middle point run a new process with only the sub array starting from the middle + 1 till the end
if (value > arr[average]) return binarySearch(arr.slice(average+1),value);
5) if the value is lower than the middle point run a new process with only the sub array starting from 0 to the middle
if (value < arr[average]) return binarySearch(arr.slice(0,average),value);
}
I hope it helps!
Note: you can use a switch statement in order to not repeat if,if,if but I like it more this way, more readable.
Upvotes: 1
Reputation: 1
Simple and Easy
let arr = [1,2,3,4,5];
function BinarySearch(arr, start, end, key) {
if(start > end) return -1;
let mid = Math.floor((start + end) / 2);
if(arr[mid] === key) return mid;
if(key > arr[mid]) {
return BinarySearch(arr, mid + 1, end, key);
} else if(key < arr[mid]) {
return BinarySearch(arr, start, mid -1, key);
}
}
BinarySearch([1,3,4,5], 0, arr.length - 1, 1); // it will return 0;
Upvotes: 0
Reputation: 782
Here is my approach for binary search recursively.
We don't slice the array because it is not needed if we can just pass down the indexes. I think that will save some time.
Function will return index if the element is found and -1 if not.
l is standing for left, r is standing for right.
function binarySearch(arr, searchNumber) {
return _binarySearch(0, arr.length -1, arr, searchNumber);
function _binarySearch(l, r, arr, searchNumber) {
const mid = Math.floor((l + r) / 2);
const guess = arr[mid];
if (guess === searchNumber) { // base case
return mid;
} else if (l === r) { // end-case the element is not in the array
return -1;
} else if (guess < searchNumber) {
return _binarySearch(mid + 1, arr.length - 1, arr, searchNumber);
} else if (guess > searchNumber) {
return _binarySearch(l, mid - 1, arr, searchNumber);
}
}
}
const list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
console.log(binarySearch(list, 4));
Upvotes: 0
Reputation: 1
Here's my recursive binary search solution:
// arr = sorted array, val = search value
// left and right are the index pointers enclosing the search value
// e.g. binarySearch([1,5,7,9,14,17,24,29,33,38,49,52,61,62,70,80,90,95,104,107,109],70)
binarySearch = (arr,val,left=0,right=arr.length) => {
position = (left,right) => {
let pos = (left + right)/2
return Math.floor(pos)
}
let i = position(left,right)
if (arr[i] === val) {
return i
}
// Base Case: if left and midpoint index coincide then there are no more possible solutions
else if (i === left) {
return -1
}
// For this case we shift the left index pointer
else if (arr[i] < val) {
return binarySearch(arr,val,i,right)
}
// For this case we shift the right index pointer
else if (arr[i] > val) {
return binarySearch(arr,val,left,i)
}
}
Upvotes: 0
Reputation: 7980
This is fully rewritten code to achieve your goal (commented, linted). This example doesn't have any checks for params.
Main error:
Disadvantages of this approach:
recursion
is slower and takes up more of the stackslice()
also there is no needed (because of the stack again)/**
* Searches recursively number from the list
* @param {Array} list
* @param {number} item Search item
* @param {number} low Lower limit of search in the list
* @param {number} high Highest limit of search in the list
* @param {number} arrLength Length of the list
* @return {(number | null)} Number if the value is found or NULL otherwise
*/
const binarySearch = ( list, item, low, high, arrLength ) => {
while ( low <= high ) {
let mid = Math.floor((low + high) / 2);
let guess = list[mid];
if ( guess === item ) {
return mid;
} else if ( guess > item ) {
high = mid - 1;
list = list.slice( 0, mid );
return binarySearch( list, item, low, high );
} else {
low = mid + 1;
list = list.slice( low, arrLength );
return binarySearch( list, item, low, high );
}
}
return null;
};
/**
* Creates the array that contains numbers 1...N
* @param {number} n - number N
* @return {Array}
*/
const createArr = ( n ) => Array.from({length: n}, (v, k) => k + 1);
const myList = createArr( 100 );
const arrLength = myList.length;
let low = 0;
let high = arrLength - 1;
console.log( '3 ' + binarySearch( myList, 3, low, high, arrLength ) ); // 2
console.log( '-1 ' + binarySearch( myList, -1, low, high, arrLength ) ); // null
I think it's more elegant solution for binary search:
const binarySearch = ( list, item ) => {
let low = 0;
let high = list.length - 1;
while ( low <= high ) {
let mid = Math.floor((low + high) / 2);
let guess = list[mid];
if ( guess === item ) {
return mid;
} else if ( guess > item ) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return null;
};
const myList = [1, 3, 5, 7, 9];
console.log( binarySearch( myList, 3 ) );
console.log( binarySearch( myList, -1 ) );
Upvotes: 0
Reputation: 121
Language agnostic, here is the simplified flow of a recursive binary search implementation, assuming we have an (initially non-empty) array [ARR] and a target [T], where we refer to the middle element of ARR as M:
// 1. If M == T, return true
// 2. If length of ARR is 0, return false (note: step 1 short circuits, ensuring we only hit step 2 if step 1 evaluates to false)
// 3. If T < M, return the result of the recursion on the lower half of ARR
// 4. If T > M, return the result of the recursion on the the latter half of ARR
Following is solution that executes the control flow outlined above. This is similar to solutions already presented in this post, with a few noteworthy differences:
function binarySearch(arr, target, start=0, stop=(arr.length-1)) {
let midPoint = Math.floor(((stop-start)/2) + start)
switch (true) {
case arr[midPoint] === target:
return true
case stop - start === 0:
return false
case arr[midPoint] < target:
return binarySearch(arr, target, midPoint+1, stop)
case arr[midPoint] > target:
return binarySearch(arr, target, start, midPoint)
}
}
Let's unpack the main differences of this implementation:
Slice is no longer used:
We are eschewing the use of Array.prototype.slice because it is a relatively expensive operation (copying half of the current array with each recursive call!) and it is not required for the algorithm to function properly.
In place of slice, we are passing the start and stop indexes of the range of the array that we have narrowed the search down to. This keeps our heap happy by not cluttering it with (potentially many) partial, impermanent copies of the same (potentially massive) array.
We are passing two additional arguments, and they have defaults:
These arguments (start and stop) serve to keep track of the range of the array we are currently recurring on. They are our alternative to slice! The default arguments enable us to call this recursive function exactly the same as we would when using slice (should the user not provide an explicit range when it is first called).
We are using a switch statement:
The speed of a switch statement vs. an if-else chain depends on several factors, most notably the programming language and the amount of conditionals in each. A switch statement was used here primarily for readability. It is a control flow that matches what we are concerned with handling in this recursive function: 4 discrete cases, each requiring different action. Additionally, a few individuals have a rare allergy to if-else statements that exceed 3 logical tests. For more information on JavaScript's switch statement and its performance vs. if-else, please take a look at this post: Javascript switch vs. if...else if...else, which links to this more informative page http://archive.oreilly.com/pub/a/server-administration/excerpts/even-faster-websites/writing-efficient-javascript.html
Upvotes: 12
Reputation: 5277
Use this code:
//_________________________________________________BEGIN notes
// Step 1. Get length of array
// Step 2. Find mid point
// Step 3. Compare if mid point is lower or higher than searched number
// Step 4. lop off unneeded side
// Step 5. go to step 1
//_________________________________________________END notes
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 44, 55];
function getMidPoint(arr, searchNumb) {
var length = arr.length;
var midPoint = Math.floor(length / 2);
var newArr = arr;
console.log(arr);
console.log("array midpoint value: " + arr[midPoint]);
if (arr[midPoint] > searchNumb) {
var newArr = arr.slice(0, midPoint);
return getMidPoint(newArr, searchNumb);
} else if (arr[midPoint] < searchNumb) {
var newArr = arr.slice(midPoint + 1, arr.length);
return getMidPoint(newArr, searchNumb);
} else {
return midPoint;
}
}
Upvotes: 4
Reputation: 546
There are 2 issues in your code :-
1) You are slicing it incorrectly 2) You have not put any base condition
This code should work hopefully :-
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 44, 55];
function getMidPoint(arr, searchNumb) {
var length = arr.length;
var midPoint = Math.floor(length / 2);
var newArr = arr;
console.log(arr);
console.log("array midpoint value: " + arr[midPoint]);
if (arr[midPoint] > searchNumb) {
var newArr = arr.slice(0, midPoint);
return getMidPoint(newArr, searchNumb);
} else if (arr[midPoint] < searchNumb) {
var newArr = arr.slice(midPoint+1, arr.length);
return getMidPoint(newArr, searchNumb);
} else {
return arr[midPoint];
}
}
This function would return undefined if element is not found in array.
Upvotes: 0
Reputation: 60143
I think that this line:
var newArr = arr.slice(0, arr[midPoint]);
should probably be:
var newArr = arr.slice(0, midPoint);
But I don't know if that's the only issue with your code. (It's not clear to me what the code is supposed to actually do. Right now "getMidPoint" appears to returns a smaller array containing the searched-for value.)
Upvotes: 1