Related
Very new to coding so please bear with me. I am attempting to solve this Kata on Codewars: https://www.codewars.com/kata/snail/train/javascript
Basically given an array like
[
[1, 2, 3, 4],
[12,13,14,5],
[11,16,15,6],
[10,9, 8, 7]
];
It would return [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16].
A snail trail spiraling around the outside of the matrix and inwards.
I am just solving for the case where the matrix is n x n where n is > 1 and an even number for now.
I got it working by declaring outputarray outside the function but I want that array to be declared within the function, hence the inclusion of this line: var outputarray = outputarray || [];
Not sure where I am going wrong.
snail = function(array) {
if (array.length == 0) {
return outputarray
}
var n = array[0].length - 1;
var outputarray = outputarray || [];
for (var i = 0; i <= n; i++) {
outputarray.push(array[0].splice(0, 1));
}
for (var i = 1; i <= n; i++) {
outputarray.push(array[i].splice(n, 1));
}
for (var i = n - 1; i >= 0; i--) {
outputarray.push(array[n].splice(i, 1));
}
for (var i = n - 1; i > 0; i--) {
outputarray.push(array[i].splice(0, 1));
}
array.pop();
array.shift();
snail(array);
}
Here's a non-recursive approach that doesn't mutate the input array. It works by keeping track of the top-left coordinate x, y and the size n of the spiral.
snail = function(array) {
const { length } = array;
const result = [];
let x = 0;
let y = 0;
let n = length;
while (n > 0) {
// travel right from top-left of spiral
for (let i = x; i < x + n; ++i) result.push(array[y][i]);
// shrink spiral and move top of spiral down
n--; y++;
// travel down from top-right of spiral
for (let i = y; i < y + n; ++i) result.push(array[i][x + n]);
// travel left from bottom-right of spiral
for (let i = x + n - 1; i >= x; --i) result.push(array[y + n - 1][i]);
// shrink spiral
n--;
// travel up from bottom-left of spiral
for (let i = y + n - 1; i >= y; --i) result.push(array[i][x]);
// move left of spiral right
x++;
}
return result;
}
console.log(snail([[1, 2, 3, 4], [12, 13, 14, 5], [11, 16, 15, 6], [10, 9, 8, 7]]));
One option is to define another function inside snail, which calls itself recursively, while also defining the outputarray inside snail. That way, outputarray isn't exposed to the outer scope, but the recursive function can still see it.
Also note that splice returns an array, so right now, your outputarray gets composed of an array of arrays. Spread into push instead to fix it, so that the outputarray becomes an array of numbers:
const input = [
[1, 2, 3, 4],
[12, 13, 14, 5],
[11, 16, 15, 6],
[10, 9, 8, 7]
];
const snail = (array) => {
const outputarray = [];
const iter = () => {
if (array.length == 0) {
return
}
var n = array[0].length - 1;
for (var i = 0; i <= n; i++) {
outputarray.push(...array[0].splice(0, 1));
}
for (var i = 1; i <= n; i++) {
outputarray.push(...array[i].splice(n, 1));
}
for (var i = n - 1; i >= 0; i--) {
outputarray.push(...array[n].splice(i, 1));
}
for (var i = n - 1; i > 0; i--) {
outputarray.push(...array[i].splice(0, 1));
}
array.pop();
array.shift();
iter(array);
};
iter(array);
return outputarray;
}
console.log(snail(input));
You could take some borders for the left, right, upper and lower indices and loop until no more indices are available.
function snail(array) {
var upper = 0,
lower = array.length - 1,
left = 0,
right = array[0].length - 1,
i = upper,
j = left,
result = [];
while (true) {
if (upper++ > lower) break;
for (; j < right; j++) result.push(array[i][j]);
if (right-- < left) break;
for (; i < lower; i++) result.push(array[i][j]);
if (lower-- < upper) break;
for (; j > left; j--) result.push(array[i][j]);
if (left++ > right) break;
for (; i > upper; i--) result.push(array[i][j]);
}
result.push(array[i][j]);
return result;
}
console.log(...snail([[1, 2, 3, 4], [12, 13, 14, 5], [11, 16, 15, 6], [10, 9, 8, 7]]));
This may not be according to the rules (or spirit?) of the kata, however, you can just glue it all together and sort.
function snail(trail) {
const numeric = (a, b) => a - b
const gather = (items, item) => items.push(parseInt(item, 10)) && items
const inline = (route, points) => points.reduce(gather, route) && route
const order = paths => paths.reduce(inline, []).sort(numeric)
return order(trail)
}
const trail = [
[1, 2, 3, 4],
[12, 13, 14, 5],
[11, 16, 15, 6],
[10, 9, 8, 7]
]
console.log(JSON.stringify(snail(trail)))
Try this:
const input = [
[1, 2, 3, 4],
[12, 13, 14, 5],
[11, 16, 15, 6],
[10, 9, 8, 7]
];
function snail(array) {
var res = [];
if (!array.length) return res;
var next = array.shift();
if (next) res = res.concat(next);
for (var i = 0; i < array.length; i++) {
res.push(array[i].pop());
}
next = array.pop()
if (next) res = res.concat(next.reverse());
for (var i = array.length - 1; i >= 0; i--) {
res.push(array[i].shift());
}
return res.concat(snail(array));
}
console.log(snail(input));
Here's my two cents, using the customary recursion:
function f(A){
return A.length > 1 ? A.splice(0,1)[0].concat(
f(A[0].map((c, i) => A.map(r => r[i])).reverse())) : A[0]
}
var A = [[ 1, 2, 3, 4], [12,13,14, 5], [11,16,15, 6], [10, 9, 8, 7]]
console.log(JSON.stringify(f(A)))
I tried to write a function that would find in a multidimensional array (with values from 3 to 7) repeating values for at least 3 times next to each other (vertical and horizontal). And if it finds that, change it for a different value. Let's say 1.
I tried to do this by loops but it doesn't seem to be a good way to solve that or I messed it up. Because for some array it works, for some it does not.
Here's my code:
function searching(array) {
for (i = 0; i < array.length; i++) {
let horizontal = array[i][0];
let howMany = 1;
for (j = 1; j < array[i].length; j++) {
if (horizontal === array[i][j]) {
howMany += 1;
horizontal = array[i][j];
if (howMany >= 3) {
for (d = j; d > j - howMany; d--) {
array[i][d] = 0;
}
}
} else {
horizontal = array[i][j];
howMany = 1;
}
}
}
for (v = 0; v < array.length; v++) {
let vertical = array[0][v];
let howMany = 1;
for (x = 1; x < array.length; x++) {
if (vertical === array[x][v]) {
howMany++;
vertical = array[x][v];
if (howMany >= 3) {
for (d = x; d > x - howMany; d--) {
array[d][v] = 0;
}
}
} else {
vertical = array[x][v];
howMany = 1;
}
}
}
}
The idea is to for example give array:
let array = [
[3, 4, 5, 6, 7],
[3, 4, 5, 6, 7],
[3, 4, 5, 5, 5],
[3, 5, 6, 7, 4]
]
And the result should be:
let result = [
[1, 1, 1, 6, 7],
[1, 1, 1, 6, 7],
[1, 1, 1, 1, 1],
[1, 5, 6, 7, 4]
]
Thanks in advance for any ideas how to solve it :) Greetings!
The problems with your current code are
(1) You're only checking individual rows and columns, when you need to be checking them both (eg, with [[2, 2], [2, 5]], when at the starting position [0][0], you need to look at both [0][1] (and its neighbors, if matching) as well as [1][0] (and its neighbors, if matching).
(2) You're not actually checking for adjacency at the moment, you're just counting up the total number of matching elements in a particular row or column.
Iterate over all indicies of the array. If an index has already been checked, return early. Recursively search for neighbors to that index, and if at least 3 matching in total are found, set them all to 1. Put all matching neighbors in the checked set to avoid checking them again (even if there were less than 2 adjacent matches found total).
setAllAdjacentToOne([
[3, 4, 5, 6, 7],
[3, 4, 5, 6, 7],
[3, 4, 5, 5, 5],
[3, 5, 6, 7, 4]
]);
// all 9s stay, the rest get set to 1:
setAllAdjacentToOne([
[2, 2, 9, 7, 7],
[2, 9, 9, 9, 7],
[3, 4, 4, 5, 5],
[9, 4, 5, 5, 9]
]);
function setAllAdjacentToOne(input) {
const output = input.map(subarr => subarr.slice());
const checked = new Set();
const getKey = (x, y) => `${x}_${y}`;
const width = input[0].length;
const height = input.length;
const getAllAdjacent = (x, y, numToFind, matches = []) => {
if (x >= width || x < 0 || y >= height || y < 0) {
return matches;
}
const key = getKey(x, y);
if (!checked.has(key) && input[y][x] === numToFind) {
checked.add(key);
matches.push({ x, y });
getAllAdjacent(x + 1, y, numToFind, matches);
getAllAdjacent(x - 1, y, numToFind, matches);
getAllAdjacent(x, y + 1, numToFind, matches);
getAllAdjacent(x, y - 1, numToFind, matches);
}
return matches;
};
output.forEach((innerRowArr, y) => {
innerRowArr.forEach((num, x) => {
const allAdjacent = getAllAdjacent(x, y, num);
if (allAdjacent.length <= 2) {
return;
}
allAdjacent.forEach(({ x, y }) => {
output[y][x] = 1;
});
});
});
console.log(JSON.stringify(output));
}
I didn't understand the question at first...
So this is my code:
let array = [
[3, 4, 5, 6, 7],
[3, 4, 5, 6, 7],
[3, 4, 5, 5, 5],
[3, 5, 6, 7, 4]
];
function replace(arr, target = 1) {
let needToChange = []; // save the index to change
const numbers = [3, 4, 5, 6, 7];
const m = arr.length; // m rows
const n = arr[0].length; // n columns
let mi = 0;
let ni = 0;
// search in row
for (mi = 0; mi < m; mi++) {
for (let x = 0; x < numbers.length; x++) {
const num = numbers[x]; // number to search
let counter = 0; // counter for this number in row mi
let tempArr = [];
for (ni = 0; ni < n; ni++) {
const currentNum = arr[mi][ni];
if (currentNum === num) {
counter++;
tempArr.push([mi, ni]);
}
}
if (counter >= 3) {
needToChange = needToChange.concat(tempArr);
}
}
}
// search in column
for (ni = 0; ni < n; ni++) {
for (let x = 0; x < numbers.length; x++) {
const num = numbers[x]; // number to search
let counter = 0; // counter for this number in row mi
let tempArr = [];
for (mi = 0; mi < m; mi++) {
const currentNum = arr[mi][ni];
if (currentNum === num) {
counter++;
tempArr.push([mi, ni]);
}
}
if (counter >= 3) {
needToChange = needToChange.concat(tempArr);
}
}
}
// replace
needToChange.forEach(([i, j]) => {
array[i][j] = target;
});
}
replace(array);
array.forEach(row => {
console.log(row.join(', '));
})
I was set the task to create an array of all permutations/ 4 digit numbers of a given array of numbers: [1,2,3,4,5,6,7,8,9]. There can be no repeats of digits as each value must be unique. Below is my solution but I am struggling to apply recursion to the process. I want it to be adaptable so if conditions changed i.e. the function must produce all combinations of 5 digit numbers or even 6 digit, as little code needs to be changed and adding recursion would allow for this easily. As you can see below the code does work but if conditions changed this would require even more nested for loops. I am looking for a recursive solution. This does not seem like a good solution but any advice would be most grateful. I have seen a lot online about creating solutions where 4P4 or 5P5 but not 9P5 kind of styles. I tried to apply heap's algorithm but to no success.
function arrayCreate((availableNumbers, userNumberArray)) {
var possibleValues = []; //empty array to house all the possible combination of values that the user could enter i.e. 1234 to 9876
var numberOfPermutations = (factorial(availableNumbers.length) / factorial(availableNumbers.length - userNumberArray.length));
var adding = true;
var firstDigit, secondDigit, thirdDigit, forthDigit =0;
var possibleDigitValue = "";
while (adding === true) {
for (var i = 0; i < availableNumbers.length; i++) {
firstDigit = availableNumbers[i];
availableNumbers.splice(i, 1);
for (var j = 0; j < availableNumbers.length; j++) {
secondDigit = availableNumbers[j];
availableNumbers.splice(j, 1);
for (var k = 0; k < availableNumbers.length; k++) {
thirdDigit = availableNumbers[k]
availableNumbers.splice(k, 1);
for (var l = 0; l < availableNumbers.length; l++) {
forthDigit = availableNumbers[l];
possibleDigitValue = (firstDigit + secondDigit + thirdDigit + forthDigit);
possibleValues.push(possibleDigitValue);
}
availableNumbers.splice(k, 0, thirdDigit);
}
availableNumbers.splice(j, 0, secondDigit);
}
availableNumbers.splice(i, 0, firstDigit);
if (possibleValues.length >= numberOfPermutations) {
adding = false;
}
}
console.log(possibleValues);
return possibleValues;
}
}
arrayCreate([1,2,3,4,5,6,7,8,9],[0,0,0,0]);
var userNumberArray = ['0', '0', '0', '0']; //empty array of 0's as this value is not allowed, this array will store the computers auto-generated number
var availableNumbers = ['1', '2', '3', '4', '5', '6', '7', '8', '9'] //array of available numbers to be picked and added to the computerNumber array
//this function is used later to calculate the possible permutations of combinations of user guess
function factorial(x) {
if (x === 0) { return 1; }
else{
return x * factorial(x-1);
}
}
function arrayCreate(availableNumbers, userNumberArray) {
var possibleValues = []; //empty array to house all the possible combination of values that the user could enter i.e. 1234 to 9876
var numberOfPermutations = (factorial(availableNumbers.length) / factorial(availableNumbers.length - userNumberArray.length));
var adding = true;
var firstDigit, secondDigit, thirdDigit, forthDigit =0;
var possibleDigitValue = "";
while (adding === true) {
for (var i = 0; i < availableNumbers.length; i++) {
firstDigit = availableNumbers[i];
availableNumbers.splice(i, 1);
for (var j = 0; j < availableNumbers.length; j++) {
secondDigit = availableNumbers[j];
availableNumbers.splice(j, 1);
for (var k = 0; k < availableNumbers.length; k++) {
thirdDigit = availableNumbers[k]
availableNumbers.splice(k, 1);
for (var l = 0; l < availableNumbers.length; l++) {
forthDigit = availableNumbers[l];
possibleDigitValue = (firstDigit + secondDigit + thirdDigit + forthDigit);
possibleValues.push(possibleDigitValue);
}
availableNumbers.splice(k, 0, thirdDigit);
}
availableNumbers.splice(j, 0, secondDigit);
}
availableNumbers.splice(i, 0, firstDigit);
if (possibleValues.length >= numberOfPermutations) {
adding = false;
}
}
return possibleValues;
}
}
console.log(arrayCreate(availableNumbers, userNumberArray));
You could take a recursive approach by iterating the items and check if the item has been chosen before. If not then take that item and check the length of the part array.
If that has the wanted length, puth the part array to the result.
If not, iterate the given array and hand over the part array.
function arrayCreate(array, size) {
var result = [];
array.forEach(function iter(parts) {
return function (v) {
var temp = parts.concat(v);
if (parts.includes(v)) {
return;
}
if (temp.length === size) {
result.push(temp);
return;
}
array.forEach(iter(temp));
}
}([]));
return result;
}
console.log(arrayCreate([1, 2, 3, 4, 5, 6, 7, 8, 9], 4).map(a => a.join('')));
console.log(arrayCreate([1, 2, 3, 4, 5, 6, 7, 8, 9], 5).map(a => a.join('')));
console.log(arrayCreate([1, 2, 3, 4, 5, 6, 7, 8, 9], 6).map(a => a.join('')));
.as-console-wrapper { max-height: 100% !important; top: 0; }
With separated function iter.
function arrayCreate(array, size) {
function iter(parts) {
return function (v) {
var temp = parts.concat(v);
if (parts.includes(v)) {
return;
}
if (temp.length === size) {
result.push(temp);
return;
}
array.forEach(iter(temp));
}
}
var result = [];
array.forEach(iter([]));
return result;
}
console.log(arrayCreate([1, 2, 3, 4, 5, 6, 7, 8, 9], 4).map(a => a.join('')));
console.log(arrayCreate([1, 2, 3, 4, 5, 6, 7, 8, 9], 5).map(a => a.join('')));
console.log(arrayCreate([1, 2, 3, 4, 5, 6, 7, 8, 9], 6).map(a => a.join('')));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Solution for any size and any options
const makeUniqPermutations = (size, options) => {
if (size > options.length) {
throw new Error('Cannot make uniq permutations with that size and options');
}
if (size === 0) {
return [''];
}
const permutations = options.reduce((acc, option, index) => {
const restSize = size - 1;
const restOptions = [
...options.slice(0, index),
...options.slice(index + 1),
];
const restPermutations = makeUniqPermutations(restSize, restOptions);
const newPermutations = restPermutations.map(permutation => `${option}${permutation}`);
return [...acc, ...newPermutations];
}, [])
return permutations;
}
const options = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
const size = 4;
console.log(makeUniqPermutations(size, options));
I am just learning javascript.I am pretty confused with manipulating multidimensional arrays.
var myarr = [
[ 7, 9, 10 ],
[ 6, 9 ],
[ 5, 9 ]
]
I want to insert zero like this.What is the smart way to do this in javascript
[
[ 7, 9, 10 ],
[ 6, 9, 0 ],
[ 5, 9, 0 ]
]
You could get first the max length of the inner arrays and push zeroes until all inner arrays have the same length.
var myarr = [[7, 9, 10], [6, 9], [5, 9]],
length = myarr.reduce(function (r, a) { return Math.max(r, a.length); }, 0);
myarr.forEach(function (a) {
while (a.length < length) {
a.push(0);
};
});
console.log(myarr);
.as-console-wrapper { max-height: 100% !important; top: 0; }
var myarr = [
[ 7, 9, 10 ],
[ 6, 9 ],
[ 5, 9 ]
]
for(var i = 0; i < myarr.length; i++) {
if(myarr[i].length < myarr.length){
myarr[i].push(0);
}
}
console.log(myarr);
Here is a solution.
var myarr = [
[7, 9, 10],
[6, 9],
[5, 9]
];
var rows = myarr.length;
var cols = 0;
for (var i in myarr) {
if (myarr[i].length > cols)
cols = myarr[i].length;
}
for (i = 0; i < rows; i++) {
for (j = 0; j < cols; j++) {
if (myarr[i][j] == undefined)
myarr[i][j] = 0;
}
}
console.log(myarr);
Best way would be first to calculate what the longest sub-array length you have, then you can pad the sub-arrays to make them all up to the same length.
The following includes a function for calculating the longest length, and another for performing the padding:
function getMax(arr) {
var max = 0;
for (var i = 0; i < arr.length; i++) {
if (arr[i].length > max)
max = arr[i].length;
}
return max;
}
function pad(arr, max) {
for (var i = 0; i < arr.length; i++) {
for (var j = arr[i].length; j < max; j++)
arr[i].push(0);
}
}
var myarr = [
[7, 9, 10],
[6, 9],
[5, 9]
];
pad(myarr, getMax(myarr));
console.log(myarr);
Seems like you need a square matrix from a 2 dimension array, so try this:
var myarr = [
[7, 9, 10],
[6, 9],
[5, 9, 1, 2, 3, 4, 5, 6, 7] // <--- for example purpose
];
var rows = myarr.length;
var cols = 0;
for(var i = 0; i < myarr.length; i++){
if(myarr[i].length > cols)
cols = myarr[i].length;
}
var limit = rows > cols ? rows : cols;
for(var i = 0; i < limit; i++){
if(myarr[i] == undefined)
myarr[i] = new Array(limit);
for(var j = 0; j < limit; j++){
if(typeof myarr[i][j] == "undefined")
myarr[i][j] = 0;
}
}
for(var i = 0; i < limit; i++){
console.log(JSON.stringify(myarr[i]));
}
var maxLength=0;
for(var i=0;i<myarr.length;i++){
if(myarr[i].length>maxLength){
maxLength=myarr[i].length
}
}
for(var i=0;i<myarr.length;i++){
if(myarr[i].length!=maxLength){
fillZeros(myarr[i])
}
}
function fillZeros(child){
while(child.length!=maxLength)
{child.push(0);}
}
If your array is a numbers only arbitrarily nested filled array, you could use a recursive function like I have here:
function fillArray(array, val){
for(var i=0; i<array.length; i++){
if(typeof(array[i]) === 'number'){
array[i] = val;
}else{
fillArray(array[i], val);
}
}
}
var test = [5,[3,8,-1,[3,4,5,2,1],[2] ],[[2,2],[3]],[[2,3],[4]],[[2,4],[5]]];
fillArray(test, 0);
using map function
var arr = [
[ 7, 9, 10 ],
[ 6, 9],
[ 5, 9]
]
var arr1 = arr.map(function(e){
var arr2 = [];
if(e.length < 3)
e.push(0);
arr2.push(e);
return arr2;
});
alert(arr1);
I'm working on an algorithm to return the difference of any pair of numbers, such that the larger integer in the pair occurs at a higher index (in the array) than the smaller integer.
Examples...
Array: [2, 3, 10, 2, 4, 8, 1]
Solution: 10 - 2 = 8
Output: 8
Array: [7, 9, 5, 6, 3, 2]
Solution: 9 - 7 = 2
Output: 2
Here is what I have but it doesn't work for all tests...
var a = [22, 2, 4, 5, 6, 444, 1, 666];
// declare variables
var minNumber = a[0], // initilize to first element
maxNumber = a[0], // --- ^
minNumberIndex = 0, // min index
maxNumberIndex = a.length - 1; // max index
// loop through each element in array
for(i = 0; i < a.length; i++) {
// find min
if (a[i] < minNumber && i < maxNumberIndex) {
minNumber = a[i];
minNumberIndex = i;
}
// find max
if (a[i] >= maxNumber && i > minNumberIndex) {
maxNumber = a[i];
maxNumberIndex = i;
}
}
// return results
console.log("max: \t" + maxNumber);
console.log("min: \t" + minNumber + "index: " + minNumberIndex);
console.log(maxNumber - minNumber);
Please help!
O(n) solution:
function maxDifference(arr) {
let maxDiff = -1;
let min = arr[0];
for (let i = 0; i < arr.length; i++) {
if (arr[i] > min && maxDiff < arr[i] - min) {
maxDiff = arr[i] - min;
}
if (arr[i] < min) {
min = arr[i];
}
}
return maxDiff;
}
console.log(maxDifference([1, 2, 3])); //2
console.log(maxDifference(3, 2, 1)); //-1
console.log(maxDifference([2, 3, 10, 2, 4, 8, 1])); //8
console.log(maxDifference([7, 9, 5, 6, 3, 2])); //2
console.log(maxDifference([22, 2, 4, 5, 6, 444, 1, 666])); //665
console.log(maxDifference([7, 9, 5, 6, 3, 2])); //2
console.log(maxDifference([666, 555, 444, 33, 22, 23])); //1
console.log(maxDifference([2, 3, 10, 2, 4, 8, 1])); //8
let MaxDifference = arr => {
let maxDiff = null;
for(let x = 0; x < arr.length; x++){
for(let y = x+1; y < arr.length; y++){
if(arr[x] < arr[y] && maxDiff < (arr[y] - arr[x])){
maxDiff = arr[y] - arr[x]
}
}
}
return maxDiff === null ? -1 : maxDiff;
}
You can have two arrays. Lets call them minlr and maxrl.
minlr - Where minlr[i] stores the minimum value till index i when going from left to right in the original array.
maxrl - Where maxrl[i] stores the maximum value till index i when going from right to left in the original array.
Once you have these 2 arrays, you iterate the arrays and find the max difference between maxrl[i] and minlr[i].
In your above examples:
minlr = {2,2,2,2,2,2,1};
maxrl = {10,10,10,8,8,8,1};
So the answer in this case would be 10 - 2 = 8.
minlr = {7,7,5,5,3,2};
maxrl = {9,9,6,6,3,2};
So the answer in this case would be 9 - 7 = 2
es6 version:
var a = [2, 3, 10, 2, 4, 8, 1];
var min = a[0];
var max = a[a.length-1];
var init = [[0,min], [a.length -1,max]];
var r = a.reduce((
res, e,i
)=>{
var [[mini, min ], [maxi ,max]] = res;
var t = res;
if(e<min && i<maxi){
t = [[i, e ], [maxi ,max]];
}
if(e>=max && i>mini){
t = [[mini, min ], [i ,e]];
}
return t;
}, init);
console.log(r[1][1]-r[0][1]);
Is this ok? for each item in the array, it looks at earlier items and adds the difference to the internal 'diffs' array (if the current item is greater). I then return the the largest value within the diffs array.
var findMaxDiff = function(arr){
var diffs = [];
for(var i = 1; i < arr.length; i++){
for(var j = 0; j < i; j++){
if(arr[i] > arr[j]){
diffs.push(arr[i]-arr[j]);
}
}
}
return Math.max.apply( Math, diffs );
}
Looping through the array and using recursion like so:
function maxDifference(a){
var maxDiff = a[1] - a[0];
for(var i = 2; i<a.length-1; i++){
var diff = a[i] - a[0];
maxDiff = diff>maxDiff ? diff : maxDiff;
}
if(a.length>1){
a.shift();
var diff = maxDifference(a);
maxDiff = diff>maxDiff ? diff : maxDiff;
}
return maxDiff;
}
var x = [2, 3, 10, 2, 4, 8, 1];
maxDifference(x); // returns 8
x = [7, 9, 5, 6, 3, 2];
maxDifference(x) // returns 2
In linear time and constant memory:
function maxDiff (nums) {
var diff = 0, left = 0, right = 0, cur_right = 0, cur_left = 0;
for (var i = 0; i < nums.length; i++) {
if (nums[i] < nums[cur_left]) {
cur_left = i;
if (cur_left > cur_right) {
cur_right = cur_left;
}
}
if (nums[i] >= nums[cur_right]) {
cur_right = i;
}
if (nums[cur_right] - nums[cur_left] > diff) {
diff = nums[cur_right] - nums[cur_left];
right = cur_right;
left = cur_left;
}
}
return [diff, left, right];
}
If you're only interested in what the difference is, and not where the numbers occur, you don't need left and right.
var maxDiff = function() {
var list = Array.prototype.slice.call(arguments, 0)[0];
var start = new Date().getTime();
if((list !== null) && (toString.call(list) !== "[object Array]")) {
console.warn("not an array");
return;
}
var maxDiff = list[1] - list[0];
var min_element = list[0];
var i, j;
for(i = 1; i < list.length; i++) {
if(list[i] - min_element > maxDiff) {
maxDiff = list[i] - min_element;
}
if(list[i] < min_element) {
min_element = list[i];
}
}
var end = new Date().getTime();
var duration = end - start;
console.log("time taken:: " + duration + "ms");
return maxDiff;
};
maxdiff = 0;
a = [2, 3, 10, 2, 4, 8, 1]
for (i=a.length-1; i >= 0; i--) {
for (j=i-1; j >= 0; j--) {
if (a[i] < a[j] ) continue;
if (a[i] -a[j] > maxdiff) maxdiff = a[i] -a[j]
}
}
console.log(maxdiff || 'No difference found')
we can use es6 + es2020 latest feature to fix this issue
function maxDiff(arr) {
var diff=0
if(arr?.length) diff=arr?.length?Math.max(...arr)-Math.min(...arr):0
return diff;
}
console.log(maxDiff([1, 2, 3])); //2
console.log(maxDiff([3, 2, 1])); //2
console.log(maxDiff([2, 3, 10, 2, 4, 8, 1])); //9
console.log(maxDiff([7, 9, 5, 6, 3, 2])); //7
console.log(maxDiff([22, 2, 4, 5, 6, 444, 1, 666])); //665
console.log(maxDiff([7, 9, 5, 6, 3, 2])); //7
console.log(maxDiff([666, 555, 444, 33, 22, 23])); //644
console.log(maxDiff([-0, 1, 2, -3, 4, 5, -6])); //11
console.log(maxDiff([2])); //0
console.log(maxDiff([])); //0
var a = [22, 2, 4, 5, 6, 444, 1, 666];
function solution(a) {
const max = Math.max.apply(null,a);
const min = Math.min.apply(null,a);
const diff = max-min;
return diff
}
console.log(solution(a))
you actually don't need any looping, just use Math.max(), Math.min(), and [].indexOf() to do the heavy-lifting for you:
function findDiff(a){
var max=Math.max.apply(0, a),
slot=a.lastIndexOf(max),
min=Math.min.apply(0, a.slice(0, slot));
if(a.length && !slot && !min-.153479 )return findDiff(a.slice(1));
return max-min;
}
//ex: findDiff([7, 9, 5, 6, 3, 2]) == 2
//ex: findDiff([666, 555, 444 , 33, 22, 23]) == 1
//ex: findDiff([2, 3, 10, 2, 4, 8, 1]) == 8