I need to write a recursive function that should return the largest number in a given array,
I'm using the method .splice() to remove the smaller numbers. When I have just one element in my array I will return that element witch would be the biggest number in the array
the logic seems working but is not returning anything, any ideas?
function findMax(arr){
// This function returns the largest number in a given array
if (arr.length === 1){
const bigNum = arr.pop();
return bigNum
}
else if (arr[0] > arr[1]){
arr.splice(1,1)
findMax(arr)
}
else{
arr.splice(0,1)
findMax(arr)
}
}
y = findMax([1,6,8,2,10,5]);
y
undefined
You need to return the results of the recursion:
function findMax(arr){
// This function returns the largest number in a given array
if (arr.length === 1){
const bigNum = arr.pop();
return bigNum
}
else if (arr[0] > arr[1]){
arr.splice(1,1)
return findMax(arr)
}
else{
arr.splice(0,1)
return findMax(arr)
}
}
y = findMax([1,6,8,2,10,5]);
console.log(y)
Another option if you're looking for something a little simpler is to compare with the result of the recursion directly and return the largest:
function findMax(arr){
// This function returns the largest number in a given array
if (arr.length <=1) return arr[0]
let [head, ...rest] = arr
let rec = findMax(rest)
return head > rec ? head : rec
// or just:
// return Math.max(head, findMax(rest))
}
y = findMax([10, 9, 14, 3, 1, -2]);
console.log(y)
Related
How to return a new array that its values are greater than its 2nd value. If the array that was passed to the function has less than two elements, function should return false.
For example,
greaterThanSecond([1,3,5,7])
should return [5, 7].
greaterThanSecond([0, -3, 2, 5])
should return [0, 2, 5].
greaterThanSecond([2])
should return false.
This is what I tried.
function valGreaterThanSecond(arr) {
for (let newArr of arr) {
if (newArr > arr[1]) {
return [newArr]
}else {
return false
}
}
}
You can try a one-liner:
[0, -3, 2, 5].filter((element, index, array) => element > array[1])
The filter function has 3 parameters:
The inspected elment
Index of the inspected element
The original array
The filter iterate through the array and you can compare to the original array's second element
function valGreaterThanSecond(arr) {
let resultArray = []
console.log(arr.length)
let checkValue = arr[1]
if(arr.length < 2)
return false
else
{
for(let i = 0 ; i < arr.length ; i++){
if(arr[i]!=checkValue && arr[i]>checkValue)
resultArray.push(arr[i])
}
return resultArray
}
}
console.log(valGreaterThanSecond([2]))
try this approach
You can try this
function greaterThanSecond(arr) {
if (arr.length < 2)
return false;
return arr.filter((item) => item > arr[1])
}
console.log(greaterThanSecond([0,-3,2,5]))
You can try this:
const greaterThanSecond = arr => {
if (arr.length > 1){
return arr.filter(e => e > arr[1])
}
return false
}
console.log(greaterThanSecond([1,3,5,7]))
In this function, at first you should check if the length of the array is not less than 2. Then we filter the array by checking if each number in the array is bigger than the second number and keep those ones in the array.
First let's try fixing your code before I am suggesting another approach.
function valGreaterThanSecond(arr) {
let newArr = [];
if (arr.length < 2) return false;
for (let elem of arr) {
if (elem > arr[1]) {
newArr = [...newArr, elem]
}
}
return newArr;
};
console.log(valGreaterThanSecond([1,3,5,7]));
The problem with your function is that once you found a number that is greater than the second element you immediately return it, thus exiting the function and returning this one element in an array, which is not what you want. If you found an element in the array that is not greater than the second element you immediately return false, which is not the behavior you want as well. In your example of [1,3,5,7] you will return false because 1 < 3 and you are out of the function at this point.
Different approach using reduce
I would like to suggest a different approach since there are a few answers using filter which is the first thing I would think about myself.
Here is a solution using the reduce function for arrays.
const greaterThanSecond = (arr) => {
if (arr.length < 2) return false;
const result = arr.reduce((acc, curr) => {
if (curr > arr[1]) return [...acc, curr];
return acc;
}, []);
return result;
}
console.log(greaterThanSecond([1,3,5,7]));
I am completing the hackerrank's 10 days of javascript challenge. The question:
write a function to take an array as an argument and then return the second largest element in the array.
I have written the code but my code is returning the largest element and not the second largest as asked.
function getSecondLargest(nums) {
// Complete the function
var largest=nums[0];
for(let i=1;i<nums.length;++i)
{
if(nums[i]>largest)
largest=nums[i];
}
var large=nums[0];
for(let j=1;j<nums.length;++j)
{
if(large<nums[j]&&large<largest)
large=nums[j];
}
return large;
}
When input array nums={2,3,6,6,5} the result is coming 6 while expected output is 5. Please help and point out the errors in the function code below.
should not initialize large with first value var large=nums[0]; because it may appear the biggest value and won't work
should use nums[j]<largest instead of large<largest as mentioned above
I think don't need second loop as all checks can be done in first loop, and you can assign prev largest to large whenever you change it:
function getSecondLargest(nums) {
var largest = nums[0];
var large;
for (let i = 1; i < nums.length; ++i) {
if (nums[i] > largest) {
large = largest;
largest = nums[i];
} else if (nums[i] > large || typeof large === 'undefined') {
large = nums[i]
}
}
return large;
}
console.log(getSecondLargest([5,1-2,3]))
console.log(getSecondLargest([-5,1,-2,3]))
GET SECOND LARGEST
first, I create new array with unique values.
let arr = [...new Set(nums)];
second, sort value using built-in function .sort().
note : by default .sort() always sorts asciibetically, but for some testcase, it doesn't work. So, I put (a, b) => { return a - b } to make sure it will work properly.
arr = arr.sort((a, b) => { return a -b });
third, get the value from arr
let result = arr[arr.length - 2] || arr[0];
finally, return the result
return result
function getSecondLargest(nums) {
let arr = [...new Set(nums)];
//Javascript's array member method .sort( always sorts asciibetically.
arr = arr.sort((a, b) => { return a - b });
let result = arr[arr.length - 2] || arr[0];
return result
}
Just one minor change:
Use nums[j]<largest instead of large<largest in the second for loop
function getSecondLargest(nums) {
// Complete the function
var largest=nums[0];
for(let i=1;i<nums.length;++i)
{
if(nums[i]>largest)
largest=nums[i];
}
var large;
//To ensure that the selected number is not the largest
for(let j=0;j<nums.length;++j)
{
if (nums[j] !== largest){
large = nums[j];
break;
}
}
for(let j=1;j<nums.length;++j)
{
if(large<nums[j]&&nums[j]!=largest)
large=nums[j];
else
console.log(large)
}
return large;
}
var secondLargest = getSecondLargest([6,3,6,6,5]);
console.log("Second largest number", secondLargest);
If you want to avoid using library functions like #ifaruki suggests, this line
if(large<nums[j]&&large<largest)
should read
if (large<nums[j] && nums[j] < largest)
Sorting and picking the second or second-to-last value fails when there are duplicates of the highest value in the input array.
Another easiest logic is to remove duplicates from the array and sort.
let givenArray = [2, 3, 6, 6, 5];
let uniqueArray = [...new Set(givenArray)];
console.log("The second largets element is", uniqueArray.sort()[uniqueArray.length - 2]);
I know you had your question answered, just thought I would provide my solution for any future users looking into this.
You can use reduce to go through the array while remembering the two largest numbers so far.
You just make a simple reduction function:
function twoMax(two_max, candidate)
{
if (candidate > two_max[0]) return [candidate,two_max[0]];
else if (candidate > two_max[1]) return [two_max[0],candidate];
else return two_max;
}
And then you use it for example like this:
let my_array = [0,1,5,7,0,8,12];
let two_largest = my_array.reduce(twoMax,[-Infinity,-Infinity]);
let second_largest = two_largest[1];
This solution doesn't require sorting and goes through the array only once.
If you want to avoid using **sort method. I think here's the easiest logic to do that, which will also work in arrays where there's duplicates of largest integer exists.
function getSecondLargest(arr) {
const largest = Math.max.apply(null, arr);
for (let i = 0; i < arr.length; i++) {
if (largest === arr[i]) {
arr[i] = -Infinity;
}
}
return Math.max.apply(null, arr);
}
console.log(getSecondLargest([5, 7, 11, 11, 11])); //7
Question
We have defined a function called countdown with one parameter (n). The function should use recursion to return an array containing the integers n through 1 based on the n parameter. If the function is called with a number less than 1, the function should return an empty array. For example, calling this function with n = 5 should return the array [5, 4, 3, 2, 1]. Your function must use recursion by calling itself and must not use loops of any kind.
function countdown(n, newArr = []){
if(n == 1){
return newArr;
}
newArr.push(n);
return countdown(n - 1)
}
console.log(countdown(5));
My Question
Is there a way to fix this code so that it works?
I can provide an alternative solution, but I do not understand it:
function countdown(n) {
if (n < 1) {
return [];
} else {
const arr = countdown(n - 1);
arr.unshift(n);
return arr;
}
}
The problem is that you do not pass on the array to the recursive call, so each recursive execution creates a new, empty array. As a consequence, it does not return the array that had a value pushed to it, but the new, empty one that is coming back from the recursive calls.
Secondly, you never push value 1 to the array. So it would be better to stop the recursion at 0 instead of 1.
So taking those two fixes, you get this:
function countdown(n, newArr=[]) {
if (n <= 0) {
return newArr;
}
newArr.push(n);
return countdown(n - 1, newArr)
}
console.log(countdown(5));
Your alternative solution is clean, because it does not need to pass an array as argument. It uses the returned array to add the next value to it (in front of it). It would have my preference.
To understand how it works, print out the intermediate values:
function countdown(n) {
if (n < 1) {
console.log("At the end of recursion. Creating and returning an empty array.");
return [];
} else {
const arr = countdown(n - 1);
console.log("Got the following array back from the recursive call:");
console.log(JSON.stringify(arr));
arr.unshift(n);
console.log("Prefixing it with " + n + " and returning the result:");
console.log(JSON.stringify(arr));
return arr;
}
}
var result = countdown(5);
yes, you can modify your solution like that
function countdown(n){
if(n == 0){
// stop the function at 0 so it will not be included in the array
return [];
}
// concat the value of n as an array with the value less than it
return [n].concat(countdown(n - 1))
}
console.log(countdown(5));
the problem in your solution is that your array initialized as an empty array every time so the final answer will be an empty array
You need to hand over the result array for the recursive call. And you need to check if no value is left, ten return the result array.
function countdown(n, result = []) {
if (n < 1) return result;
result.push(n);
return countdown(n - 1, result);
}
console.log(countdown(5));
As another approach, you could return an array and for the exit condition take the final value, otherwise take n and the spreaded result of the recursive call.
function countdown(n) {
if (n < 1) return [];
return [n, ...countdown(n - 1)];
}
console.log(countdown(5));
At this point we will create the countdown function which call itself and called recursion.
function countdown(n) {
if (n < 1) {
return [];
} else {
console.log(n, "before calling");
const arr = countdown(n - 1);
console.log(n, "after calling");
return arr;
}
}
console.log(countdown(5));
And now when we know that the "before calling" is place where n is decrease and the "after calling" is place where n is increase, based on that we can do this.
const arr = [];
function countdown(n) {
if (n < 1) {
return arr;
} else {
arr.push(n);
return countdown(n - 1);;
}
}
console.log(countdown(5));
In my JavaScript file, I have a variable num with a value of 3. What I wanna do is get any number that is not 3, between 1 and 4. To give you an idea of it:
if number equal 3
return [1,2,4]
elif number equal 1
return [2,3,4]
elif number equal 2
return [1,3,4]
elif number equal 4
return [1,2,3]
You could use Array#filter and return the unequal values.
function getArrayWithout(array, v) {
return array.filter(function (a) { return a !== v; });
}
var array = [1, 2, 3, 4];
console.log(getArrayWithout(array, 3));
You don't need the if/else to do so. You could just define which is the number that you want to exclude and then filter it out from the numbers array.
var numberToExclude = 3;
var numbers = [1,2,3,4];
console.log(numbers.filter(number => number !== numberToExclude));
For further info, regarding the filter method please have a look here.
Iterate over the range using a simple for loop and generate array by checking the number.
function genArray(num, start = 1, end = 4) {
// initialize the result array
var res = [];
// iterate based on the range
for (var i = start; i <= end; i++)
// push into the array if number is not `num`
i != num && res.push(i)
// return the result
return res;
}
console.log(genArray(3));
console.log(genArray(2));
console.log(genArray(3, 1, 10));
console.log(genArray(3, 2, 10));
You could do with Array#splice method
function except(num){
var arr=[1,2,3,4]
if(arr.indexOf(num) > -1)
arr.splice(arr.indexOf(num),1);
return arr
}
console.log(except(3))
console.log(except(1))
console.log(except(2))
I am trying to have fun with my buddy who solved the problem mentioned in 8m 7s, and for me it is already 20m gone. I can't figure out how to handle unlimited nested array in javascript.
The problem is this:
// i will be an array, containing integers, strings and/or arrays like itself.
// Sum all the integers you find, anywhere in the nest of arrays.
So
arraySum([[1,2,false],'4','5']) will return 3 (passed)
arraySum([[1,2,3],4,5]) will return 15 (passed)
arraySum([[[[[[[[[1]]]]]]]], 1]) will return 2 (failed)
The code I wrote is:
function arraySum(i) {
sum = 0;
tmp =0;
for (var a=0; a<i.length; a++){
if (i[a] instanceof Array) {
ar = i[a];
for (var j=0; j<ar.length; j++){
tmp +=ar[j];
}
}
if (typeof i[a] == "number")
sum += i[a];
console.log(sum);
}
return sum + tmp;
}
As you can see it does not handle the last situation that I failed as I can't figure out how to handle unlimited nest in JS.
Any idea will be much appreciated.
Also try to finish it before 8m 7s, which my buddy finished in.
Inside of the if (i[a] instanceof Array) { part, you'll have to use recursion to operate on nested arrays with the same arraySum function, not just use another loop. Try this:
var arraySum = (function () {
"use strict";
var sumFunc, isArray;
sumFunc = function (arr) {
var sum, i, j, cur, toAdd;
sum = 0;
for (i = 0, j = arr.length; i < j; i++) {
cur = arr[i];
toAdd = 0;
if (isArray(cur)) {
toAdd = sumFunc(cur);
} else if (typeof cur === "number") {
toAdd = cur;
}
sum += toAdd;
}
return sum;
};
isArray = Array.isArray || function (obj) {
return Object.prototype.toString.call(obj) === "[object Array]";
};
return sumFunc;
}());
DEMO: http://jsfiddle.net/Q7JPM/1
The function just loops through all items in an array, and returns the sum of any numbers found inside. If the item is an array itself, it calls arraySum and passes that array...adding the result to the sum. If it's a number, it simply adds that to the sum.
You have to use recursion:
http://jsfiddle.net/HMnat/2
function arraySumRec(theArray)
{
var sum=0;
for (var i=0;i<theArray.length;i++)
{
if (theArray[i] instanceof Array)
{
sum=sum+arraySumRec(theArray[i]);
}
else
{
if (typeof(theArray[i])=="number")
{
sum=sum+theArray[i];
}
}
}
return sum;
}
Took me 3 minutes 47 seconds (due to a typo, ha ha).
The Javascript Array reduce method is perfect for solving this kind of problem. The reduce method takes a function with at least two arguments: the accumulator and the current element of the array. In the body of the function, you specify how each element should affect the accumulator. The second argument to the function is the starting value of the accumulator.
function sum(x) {
return x.reduce(function(accumulator, currentValue) {
if (typeof currentValue === "number") {
return accumulator + currentValue;
} else if (currentValue instanceof Array) {
return accumulator + sum(currentValue);
} else {
return accumulator;
}
}, 0);
}
JSFIDDLE
The function sum takes an array, and the reduce method reduces it to a single value. In the "else if" branch, where we find a nested array, we can simply call sum on it, get back a single value, and add that to our accumulator. In the "else" branch, we haven't found the kinds of values we're interested in so we leave the accumulator unchanged.
The documentation at MDN provides a good explanation of Array reduce with examples.
function arraySum(i) {
var l = i.length, sum = 0;
while (l--) {
if (typeof i[l] !== 'number' && !(i[l] instanceof Array)) continue;
if (i[l] instanceof Array) { sum += arraySum(i[l]); continue; }
sum += i[l];
}
return sum;
}
Non-Recursive using a stack.
function arraySum(arr)
{
var sum = 0;
while(arr.length != 0)
{
var value = arr.pop();
if(value instanceof Array)
{
for (i= 0; i< value.length; ++i)
arr.push(value[i]);
}
else if(typeof value === "number")
sum += value;
}
return sum;
}
var arr = [1, 2, [3, 4, [[[5]]]]];
console.log(arraySum(arr));
If we focus on the right parts, we can save ourselves the tedium from focusing on the wrong parts -
function arraySum (t)
{ switch (t?.constructor)
{ case Array:
return t.reduce((r, v) => r + arraySum(v), 0)
case Number:
return t
default:
return 0
}
}
console.log(arraySum([[1,2,false],'4','5']))
console.log(arraySum([[1,2,3],4,5]))
console.log(arraySum([[[[[[[[[1]]]]]]]], 1]))
3
15
2
If ?. is not yet supported in your environment, you can swap it out -
switch (t?.constructor)
switch (t && t.constructor) // <- where ?. is unsupported
Edit: it took me 2,769 days to answer the question but only a few minutes to write it :D