sum of an array using recursion Javascript - javascript

Looking for a way to solve this problem by recursing sum(). Right now, the code works, but I am supposed to call sum() more than once, and it should not mutate the input array.
var sum = function(array) {
if(array.length === 0){
return 0;
}
function add(array, i){
console.log(array[i]);
if(i === array.length-1){
return array[i];
}
return array[i] + add(array, i+1);
}
return add(array, 0);
};
sum([1, 2, 3, 4, 5, 6]) //21

A one-liner that meets all your requirements:
var sum = function(array) {
return (array.length === 0) ? 0 : array[0] + sum(array.slice(1));
}
// or in ES6
var sum = (array) => (array.length === 0) ? 0 : array[0] + sum(array.slice(1));
// Test cases
sum([1,2,3]); // 6
var s = [1,2,3];
sum(s); // 6
sum(s); // 6
Reasoning
In a recursive call, you need to model your task as reduction to a base case. The simplest base case in this case is the empty array - at that point, your function should return zero.
What should the reduction step be? Well you can model a sum of an array as the result of adding the first element to the sum of the remainder of the array - at some point, these successive calls will eventually result in a call to sum([]), the answer to which you already know. That is exactly what the code above does.
array.slice(1) creates a shallow copy of the array starting from the first element onwards, and no mutation ever occurs on the original array. For conciseness, I have used a ternary expression.
Breakdown:
sum([1,2,3])
-> 1 + sum([2,3])
-> 1 + 2 + sum([3])
-> 1 + 2 + 3 + sum([])
-> 1 + 2 + 3 + 0
-> 6

You're on the right track, but consider that sum could take an optional second argument (that defaults to zero) that indicates the position to start summing from...
function sum(array, n) {
n ||= 0;
if (n === array.length) {
return 0;
} else {
return array[n] + sum(array, n + 1);
}
}

function sumNumbersRecursively(input){
if (input.length == 0){
return 0;
} else{
return input.shift() + sumNumbersRecursively(input);
}
}
console.log(sumNumbersRecursively([2,3,4]))

You don't really need the add function inside your sum function just inline the function and initiate with, 0 as a starting point, or optionally check the i variable for undefined and initialize it to 0!
var sum = function(array, i) {
if(array.length === 0){
return 0;
}
console.log(array[i]);
if(i === array.length-1){
return array[i];
}
return array[i] + sum(array, i+1);
};
console.log(sum([1, 2, 3, 4, 5, 6],0)) //21

You have two solutions:
you can use .reduce() method
or perform a simple tail recursion
With reduction:
function sum(a, b) {
return a + b;
}
const array = [1, 2, 3, 4, 5, 6];
//In our reduce, we will apply our sum function,
//and pass the result as the next value
const res = array.reduce(sum);
With recursion:
function sumRec(array, acc = 0, index) {
//We will update our accumulator, and increment
// the value of our current index
return index === array.length
? acc
: sumRec(array, acc += array[index], ++index);
}
console.log(sumRec(array, 0, 0));
Personally, I find the first solution more elegant.

arr = [1,2,3,4]
sum = arr.reduce((acc, curr)=> acc+curr)

function sumArr(arr){
if(arr.length>1){
return arr.pop()+sumArr(arr);
}else{
return arr[0];
}
}

If you have to call sum more than once, then use the binary approach: split the array in half and recur on each piece. When you get to a length of 1, return the single value.
Does this work for you? I'm afraid I don't recall the JS syntax for array slices, so my recursion statement may be wrong in the details.
var sum = function(array) {
if(array.length === 1){
return array[0];
}
mid = array.length / 2
return sum(array[0:mid-1]) + sum(array[mid:array.length-1])
};
sum([1, 2, 3, 4, 5, 6]) //21

Related

Get 5 closest elements to an element in array including that element

I am trying to get 5 closest elements to given element, including that element, in array. For example, if we have:
const arr = [1, 2, 3, 4, 7, 11, 12, 13, 15, 17]
and I want to get 5 closest elements to 11, it should return [4, 7, 11, 12, 13]. If i pass 1 it should return [1, 2, 3, 4, 7]. If I pass 15 it should return [11, 12, 13, 15, 17].
I'm not sure what you meant;
You might've meant a code to find the element and return the five nearest elements to it by place in the array;
Or you might've meant a code to find the 5 numbers closest to a number you say.
IF you meant the first case
There are two ways to do so,
A value as a parameter
Use this code:
function closestNByValue(arr, value, n) {
let ind = arr.indexOf(value);
let finalArr = [];
if (n > arr.length) {
finalArr = Array.from(arr);
} else if (ind == -1) {
finalArr = [];
} else if (ind <= n/2 - 0.5) {
finalArr = arr.slice(0, n);
} else if (ind >= (arr.length - n/2) - 0.5) {
finalArr = arr.slice(-n);
} else if (n%2 == 0) {
finalArr = arr.slice(ind-(n/2), ind+(n/2));
} else {
finalArr = arr.slice(ind-(n/2 - 0.5), ind+(n/2 + 0.5));
}
return finalArr;
}
console.log(closestNByValue([1, 2, 3, 4, 7, 11, 12, 13, 15, 17], 11, 5))
How does it do the job?
Okay first we need to find the index of the value and save it in ind (short form of 'index') and we check multiple different situations for what the ind is so we'd be able to output the best answer as finalArr.
There are two exceptions; what if there was no such value in our array? then ind = -1 and we'd return an empty array; or what if the number of elements nearby that we seek is larger than or equal to the arr.length? then we'd return all of the arr.
But if there were no exceptions, there are three different situations for the ind; first, ind is a number that makes us have all of the finalArr values from the first of arr, second, ind be a number that makes us have all of the finalArr values from the last of arr, and third, ind being a number that we have to select half from the indexes smaller than ind and half, larger.
If it is the third way, the way we select we'd be different depending on the oddity of the numbers we want to select.
And we'll have a conditional statement for each situation and return the finalArr.
An index as a parameter
function closestNByIndex(arr, ind, n) {
let finalArr = [];
if (n > arr.length) {
finalArr = Array.from(arr);
} else if (ind == -1) {
finalArr = [];
} else if (ind <= n/2 - 0.5) {
finalArr = arr.slice(0, n);
} else if (ind >= (arr.length - n/2) - 0.5) {
finalArr = arr.slice(-n);
} else if (n%2 == 0) {
finalArr = arr.slice(ind-(n/2), ind+(n/2));
} else {
finalArr = arr.slice(ind-(n/2 - 0.5), ind+(n/2 + 0.5));
}
return finalArr;
}
console.log(closestNByIndex([1, 2, 3, 4, 7, 11, 12, 13, 15, 17], 5, 5))
Similar to the first code it works, though we have the index and we don't search for it.
The point is, if you use the function with value, it'd do the nearest 5 elements of the first value that equals the entry but such confusion is not being tolerated in the second code.
IF you meant the second case
This is a code I coded:
const arr = [1, 2, 3, 4, 7, 11, 12, 13, 15, 17];
function allDiff(arr, num1, num2) {
const finalArr = [];
const x = Math.abs(num2 - num1);
for (let y = 0; y < arr.length; y++) {
if (Math.abs(arr[y] - num1) == x) {
finalArr.push(arr[y]);
}
}
return finalArr;
}
function deleteArr(arr, delet) {
for (let x = 0; x < arr.length; x++) {
if (delet.includes(arr[x])) {
delete arr[x];
}
}
return arr;
}
function closest(arr, num) {
const map = new Map()
arr2 = Array.from(arr);
let key, value;
for (let x = 0; x < arr2.length; x++) {
key = Math.abs(arr2[x] - num);
value = allDiff(arr2, num, arr2[x]);
arr2 = deleteArr(arr2, value);
map.set(key, value);
}
return map;
}
function closestN(arr, num, n) {
const map = closest(arr, num);
const mapKeys = Array.from(map.keys());
const mapKeysSorted = mapKeys.sort(function(a, b) {
return a - b
});
let finalArr = [];
let y;
for (let i = 0; i < mapKeysSorted.length; i++) {
if (n <= 0) {
break;
}
y = map.get(mapKeysSorted[i]);
if (n < y.length) {
finalArr = finalArr.concat(y.slice(0, n + 1));
break;
}
finalArr = finalArr.concat(y);
n -= y.length;
}
return finalArr;
}
console.log(closestN(arr, 11, 5));
It might be a little too long, but I have programmed it as you can give it any array (arr) with integer values, an integer (num) that you'd like it to be the base and another integer (n) for the number of the size of the output array, 5 in this case.
Explaining the code
The function closest would return a map of (the difference between the numbers, a list of the numbers in the arr that differs the number equal to their key).
The main function, closestN, calls the closest function and saves the map in the map variable.
Then it sorts the keys of the map in mapKeysSorted.
Now, a for loop loops through the mapKeySorted array and pushes new elements to the finalArr until the size of the finalArr reaches the number of elements we seek.
The main function is the closestN.
Here's a way to get to your goal:
To start, first thing to do is finding the index of the wanted number in the array. Example index of 1 in your array arr is 0. The index will help in extracting the numbers later on. The method findIndex will help us in finding the index.
Then, we need to find the position at which will start extaracting the closest numbers (in terms of position not value). As seen from the desired output you have provided, usually you want the returned array to be in the following structure:
output: [
2 nearest numbers (from N left),
the wanted number,
2 nearest numbers (from N right)
]
This can get tricky so we should make sure to deal with some edge case like when the wanted element is sitting at position 0.
Extract the numbers and return them as an array as described by your desired output. The use of slice method will come in handy here which allow us to extract the numbers just as we need.
Here's a live demo demonstrating solution:
const arr = [1, 2, 3, 4, 7, 11, 12, 13, 15, 17],
/** a function that returns an array containing the "5" (depending on "arr" length that could be less) nearest numbers (in terms of position) in "arr" array to the supplied number "n" */
findClosestNumbers = n => {
/** make sure we don't exceed the array length */
const toTake = 5 > arr.length ? arr.length : 5,
/** find the index of the wanted nulber "n", if "-1" is returned then "n" cannot be found ion the array "arr" */
idx = arr.findIndex(el => n == el),
/**
* from where we should start returning the nearest numbers (the position of the first number to extract from "arr"
* the below condition help deal with some edge cases like when "n" is the last element in "arr"
*/
startIdx = idx + toTake / 2 > arr.length ?
arr.length - 5 :
(idx - 2 >= 0 ?
idx - 2 :
0);
/** return the nearest numbers or return an empty array "[]" if the number "n" is not found on the array "arr" */
return idx == -1 ? [] : arr.slice(startIdx, startIdx + 5);
};
/** run for various scenarios */
console.log('For 1 =>', findClosestNumbers(1));
console.log('For 11 =>', findClosestNumbers(11));
console.log('For 15 =>', findClosestNumbers(15));
console.log('For 17 =>', findClosestNumbers(17));
.as-console-wrapper {
max-height: 100%!important;
}
The demo above is meant to help you understand how things could work and it is not the only way to get to your goal. Also, because I kept it as simple as possible, the above demo is wide open for improvements.

Closure parameter not receiving the parameters, instead just it on the side

working with recursion and closures but not receiving the correct output.
The recursion block works correctly to take out elements and then add them to a total.
but when I try to implement the closure to the problem is doesn't work and the output is just the function instead of the correct output
let arr = [1, 2, 3, 4, 5];
function add(arr, total = 0) {
if (arr.length === 0) return total;
// console.log(total, 'total')
numberToAdd = arr[0];
// console.log(numberToAdd, 'number to be added to the total')
arr.shift();
// console.log(arr, 'array after taking out the first element', arr.length);
// console.log('total before recursion', total)
return num + add(arr, total + numberToAdd);
}
addTo15 = add(arr)
console.log(addTo15(100))
/** expected output: 115
*
* instead this outputs
*
* 100function(num) {
return num + add(arr, total + numberToAdd) ;
}
*/
Your question isn't quite clear to me, but my best guess is that you want to do something like this:
const addArrTo = ([n, ...ns]) => (num) =>
n == undefined
? num
: addArrTo (ns) (num + n)
const addTo15 = addArrTo ([1, 2, 3, 4, 5])
console .log (addTo15 (100))
which can also be written like this, if it's more familiar:
const addArrTo = (arr) => (num) =>
arr .length == 0
? num
: addArrTo (arr .slice (1)) (num + arr [0])
or even as
function addArrTo (arr) {
return function (num) {
return arr .length == 0
? num
: addArrTo (arr .slice (1)) (num + arr [0])
}
}
Each of these versions is a function that accepts an array of numbers and returns a function. The returned function takes a starting number, and then recursively calls itself, adding the current number from the input array to the running total.

Bonfire Algorithm Challenge: Where Do I Belong on javascript

Hello guys I am currently stuck on this algorithm challenge on FCC. This is what the challenge is all about:
Return the lowest index at which a value (second argument) should be inserted into an array (first argument) once it has been sorted. The returned value should be a number.
For example, getIndexToIns([1,2,3,4], 1.5) should return 1 because it is greater than 1 (index 0), but less than 2 (index 1).
Likewise, getIndexToIns([20,3,5], 19) should return 2 because once the array has been sorted it will look like [3,5,20] and 19 is less than 20 (index 2) and greater than 5 (index 1).
This is my code here:
function getIndexToIns(arr, num) {
var getIndx;
var newArr = arr.sort(function (a, b) {
return (a - b);
});
for (i = 0; i < newArr.length; i++) {
if (num > newArr[i]) {
getIndx = newArr.indexOf(newArr[i]);
}
}
return getIndx;
}
getIndexToIns([10, 20, 30, 40, 50], 35);
when I ran the code it worked but it isn't passing the test. Guys I need your help. Thanks
The solutions proposed so far tend to follow literally the request of the problem: first sort the array, then find the index where to insert the number. That brings you to loop over the array twice. More if you have to clone the array. That is slow, even without considering all the garbage we end up creating ...
Can we do better? I think so.
How about "count how many numbers in the array are less or equal to the number to insert". This achieves the same goal but let's us do it looping only once over the array.
function getIndexToIns(arr, num) {
return arr.reduce(function (c, x) { return x <= num ? c+1 : c }, 0);
}
console.log(getIndexToIns([10, 20, 30, 40, 50], 35)); // 3
console.log(getIndexToIns([20,3,5], 19)); //2
console.log(getIndexToIns([1,2,3,4], 1.5)); //1
console.log(getIndexToIns([1,2,3,4], 1)); //1
console.log(getIndexToIns([1,2,3,4], 0)); //0
how about that?! twice as fast*, yay!
* it's probably not really twice as fast, if you have to be nitpicky about my claims...
EDIT
Actually I can do better. That ternary if introduces some branching in the code that bothers me. We could take advantage of javascript weirdness to avoid it
arr.reduce(function (c, x) { return c + (x <= num) }, 0)
why? because when combined with a numeric operation true is converted to 1 and false to 0
That removes the extra branching from the code so it's going to be slightly faster than the previous version ... And it would also be easier to unit test, if you care about that.
You could iterate and check if the actual value is greater then the number. Then retuen the actual index. If no value match, then return the length of the array as new input index.
function getIndexToIns(arr, num) {
var i;
arr.sort(function(a, b){
return a - b;
});
for (i = 0; i < arr.length; i++) {
if (arr[i] > num) {
return i;
}
}
return arr.length;
}
console.log(getIndexToIns([10, 20, 30, 40, 50], 35)); // 3
console.log(getIndexToIns([1, 2, 3, 4], 1.5)); // 1
console.log(getIndexToIns([20, 3, 5], 19)); // 2
console.log(getIndexToIns([4, 3, 2, 1], 5)); // 4
Alternative version without using a method from the Array API
function getIndexToIns(array, value) {
var i = array.length,
p = 0;
while (i--) {
p += array[i] <= value;
}
return p;
}
console.log(getIndexToIns([10, 20, 30, 40, 50], 35)); // 3
console.log(getIndexToIns([1, 2, 3, 4], 1.5)); // 1
console.log(getIndexToIns([20, 3, 5], 19)); // 2
console.log(getIndexToIns([4, 3, 2, 1], 5)); // 4
If I understand correctly I think you should look at the previous item from the list:
function getIndexToIns(arr, num) {
var getIndx = 0;
var newArr = arr.sort(function (a, b) { return (a - b); });
for (i = 1; i < newArr.length; i++) {
if (num >= newArr[i-1]) {
getIndx = i;
}
}
return getIndx;
}
console.log(getIndexToIns([10, 20, 30, 40, 50], 35)); // 3
console.log(getIndexToIns([20,3,5], 19)); //2
console.log(getIndexToIns([1,2,3,4], 1.5)); //1
console.log(getIndexToIns([1,2,3,4], 1)); //1
console.log(getIndexToIns([1,2,3,4], 0)); //0
Thanks Guys for all your assistance. I figured it out and this is the final code here
function getIndexToIns(arr, num) {
var getIndx;
var newArr = arr.sort(function(a, b){
return (a - b);
});
for (i = 0; i < newArr.length; i++) {
if (newArr[i] > num || newArr[i] === num) {
return i;
}
}
return newArr.length;
}
My solution to this problem.
const getIndexToIns = (arr, num) => {
let newArr = arr.concat(num);
newArr.sort(function(a, b) {
return a - b;
});
let index = newArr.indexOf(num);
return index;
}

How to create a binary search with recursion

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
}
}
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
You are slicing it wrong.
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;
}
}
Also, if the search element is not in array, this will go on infinitely. Add a base case for that too.
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.)
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.
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.
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.
This is fully rewritten code to achieve your goal (commented, linted).
This example doesn't have any checks for params.
Main error:
wrong slicing
Disadvantages of this approach:
recursion is slower and takes up more of the stack
slice() 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 ) );
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)
}
}
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));
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;
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)
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
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);
}
}
}
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);
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.

selecting the two biggest values in an array

I'm trying to write a function that finds the two biggest value inside an array of numbers and stores them inside a new array. I'm unable to first remove the first biggest number from the original array and then find the second biggest.
here is my code:
function choseBig (myArray) {
//var myArray = str.split(" ");
var result = [];
var firstBig;
var secondBig;
// select the biggest value
firstBig = Math.max.apply(Math, myArray);
// find its index
var index = myArray.indexOf(firstBig);
// remove the biggest value from the original array
var myArray_2 = myArray.slice((index -1), 1);
// choose the second biggest value
secondBig = Math.max.apply(Math, myArray_2);
// push the results into a new array
result.push(firstBig, secondBig);
return result;
}
console.log(choseBig ([1,2,3,4,5,9]));
At first glance, I'd suggest:
function choseBig(myArray) {
return myArray.sort((a, b) => b - a).slice(0, 2);
}
console.log(choseBig([1, 2, 3, 4, 5, 9]));
To extend the above a little, for example offering the user the option to specify whether the returned values should be the highest numbers, or the lowest numbers, and how many they wish returned, I'd offer the following:
function choseBig(myArray, opts) {
// 'max': Boolean,
// true: returns the highest numbers,
// false: returns the lowest numbers
// 'howMany': Number,
// specifies how many numbers to return:
var settings = {
'max': true,
'howMany': 2
};
// ensuring we have an Object, otherwise
// Object.keys( opts ) returns an error:
opts = opts || {};
// retrieving the keys of the opts Object, and
// uses Array.prototype.forEach() to iterate over
// those keys; 'o' (in the anonymous function) is
// the array element (the property-name/key) from
// the array Object keys over which we're iterating:
Object.keys(opts).forEach(function(o) {
// updating the settings Object to the new values
// (if any is specified) to those set in the user-
// supplied opts Object:
settings[o] = opts[o];
});
// here we first sort the Array, using a numeric sort;
// using ES2015 Arrow functions. 'a' and 'b' are supplied
// by Array.prototype.sort() and refer to the current ('a')
// and next ('b') array-elements. If b - a is less than zero
// b is moved to a lower index; if a - b is less than zero
// a is moved to a lower index.
// Here we use a ternary operator based on whether settings.max
// is true; if it is true we sort to move the larger number to
// the lower index; otherwise we sort to move the smaller number
// to the lower index.
// Then we slice the resulting array to return the numbers from
// the 0 index (the first number) to the settings.howMany number
// (the required length of the array).
// this is then returned to the calling context.
return myArray.sort((a, b) => settings.max === true ? b - a : a - b).slice(0, settings.howMany);
}
console.log(choseBig([1, 2, 3, 4, 5, 9], {
// here we specify to select the largest numbers:
'max': true,
// we specify we want the 'top' three numbers:
'howMany': 3
}));
function choseBig(myArray, opts) {
var settings = {
'max': true,
'howMany': 2
};
opts = opts || {};
Object.keys(opts).forEach(function(o) {
settings[o] = opts[o];
});
return myArray.sort((a, b) => settings.max === true ? b - a : a - b).slice(0, settings.howMany);
}
console.log(choseBig([1, 2, 3, 4, 5, 9], {
'max': true,
'howMany': 3
}));
JS Fiddle demo.
References:
Array.prototype.forEach.
Array.prototype.slice().
Array.prototype.sort().
Conditional (Ternary) Operator: statement ? ifTrue : ifFalse
How do you use the ? : (conditional) operator in JavaScript?.
Object.keys().
Why not just sort it (descending order) and take the first two entries
biggest = myArray.sort(function(a,b){return b - a}).slice(0,2);
The answers above are probably better and more compact, but in case you don't want to use sort() this is another option
function choseBig (myArray) {
var result = [], firstBig, secondBig;
// select the biggest value
firstBig = Math.max.apply(Math, myArray);
// find its index
var index = myArray.indexOf(firstBig);
// remove the biggest value from the original array
myArray.splice((index), 1);
secondBig = Math.max.apply(Math, myArray);
// push the results into a new array
result.push(firstBig, secondBig);
return result;
}
console.log(choseBig ([1,2,3,4,5,9]));
A linear solution with Array#reduce without sorting.
var array = [1, 2, 3, 4, 5, 9],
biggest = array.reduce(function (r, a) {
if (a > r[1]) {
return [r[1], a];
}
if (a > r[0]) {
return [a, r[1]];
}
return r;
}, [-Number.MAX_VALUE, -Number.MAX_VALUE]);
document.write('<pre>' + JSON.stringify(biggest, 0, 4) + '</pre>');
Edit: more than one biggest value
var array = [1, 2, 3, 4, 5, 9, 9],
biggest = array.reduce(function (r, a) {
if (a > r[1]) {
return [r[1], a];
}
if (a > r[0]) {
return [a, r[1]];
}
return r;
}, [-Number.MAX_VALUE, -Number.MAX_VALUE]);
document.write('<pre>' + JSON.stringify(biggest, 0, 4) + '</pre>');
With Math#max and Array#splice
var first = Math.max(...arr)
arr.splice(arr.indexOf(first))
var second = Math.max(...arr)
and with ES6 spread operator
I like the linear solution of Nina Scholz. And here's another version.
function chooseBig (myArray) {
var a = myArray[0], b = myArray[0];
for(i = 1; i < myArray.length; i++) {
if (myArray[i] === a) {
continue;
} else if (myArray[i] > a) {
b = a;
a = myArray[i];
} else if (myArray[i] > b || a === b) {
b= myArray[i];
}
}
return [a, b];
}
If you want to retrieve the largest two values from a numeric array in a non-destructive fashion (e.g. not changing the original array) and you want to make it extensible so you can ask for the N largest and have them returned in order, you can do this:
function getLargestN(array, n) {
return array.slice(0).sort(function(a, b) {return b - a;}).slice(0, n);
}
And, here's a working snippet with some test data:
function getLargestN(array, n) {
return array.slice(0).sort(function(a, b) {return b - a;}).slice(0, n);
}
// run test data
var testData = [
[5,1,2,3,4,9], 2,
[1,101,22,202,33,303,44,404], 4,
[9,8,7,6,5], 2
];
for (var i = 0; i < testData.length; i+=2) {
if (i !== 0) {
log('<hr style="width: 50%; margin-left: 0;">');
}
log("input: ", testData[i], " :", testData[i+1]);
log("output: ", getLargestN(testData[i], testData[i+1]));
}
<script src="http://files.the-friend-family.com/log.js"></script>
[1,101,22,202].sort(function(a, b){return b-a})[0]
[1,101,22,202].sort(function(a, b){return b-a})[1]

Categories