How can I reduce duplication in my JavaScript if syntax? - javascript

I want to reduce duplication in my JavaScript syntax.
No matter how much I think about it, it doesn't come to mind.
It doesn't matter if it is for loop or any syntax!
i add some of case and result
if if it is correct answer would be result
// case 1
// const max = [1, 31, 0, 0]
// const min = [1, 31];
// result = [3, 5]
// case 2
// const max = [0, 0, 0, 0, 0, 0]
// const min = [0, 0]
// result = [1, 6]
// case 3
// const max = [45, 4, 35, 20, 3, 9]
// const min = [45, 4, 35, 20, 3, 9]
// result = [1, 1]
if (max.length === 6) {
answer[0] = 1;
} else if (max.length === 5) {
answer[0] = 2;
} else if (max.length === 4) {
answer[0] = 3;
} else if (max.length === 3) {
answer[0] = 4;
} else if (max.length === 2) {
answer[0] = 5;
} else {
answer[0] = 6;
}
if (min.length === 6) {
answer[1] = 1;
} else if (min.length === 5) {
answer[1] = 2;
} else if (min.length === 4) {
answer[1] = 3;
} else if (min.length === 3) {
answer[1] = 4;
} else if (min.length === 2) {
answer[1] = 5;
} else {
answer[1] = 6;
}

is max and min length between 1 and 6? because judging your code, it looks like it.
answer[0] = 7 - max.length
sure looks a bit neater, at the least you could eliminate many if blocks and leave the else block in case max.length is not an integer between 1 and 6
//pseudocode
if( max.length between 1 and 6 inclusive) {
answer[0] = 7- max.length
} else {
answer[0] = some default value, 6?
}
the 7 looks like a magic number, but with more context, you can name it something better

const getAnswers = x => (x < 1 || x > 6) ? 6 : 7 - x;
// case 1
let max = [1, 31, 0, 0]
let min = [1, 31];
// result = [3, 5]
let answer = [getAnswers(max.length), getAnswers(min.length)];
console.log('max.length: ', max.length, ' min.length: ', min.length, ' answer array: ', answer);
// case 2
max = [0, 0, 0, 0, 0, 0]
min = [0]
// result = [1, 6]
answer = [getAnswers(max.length), getAnswers(min.length)];
console.log('max.length: ', max.length, ' min.length: ', min.length, ' answer array: ', answer);
// case 3
max = [45, 4, 35, 20, 3, 9]
min = [45, 4, 35, 20, 3, 9]
// result = [1, 1]
answer = [getAnswers(max.length), getAnswers(min.length)];
console.log('max.length: ', max.length, ' min.length: ', min.length, ' answer array: ', answer);

By reducing duplication, do you mean you want to decrease the length of your code or increase readability?
If you want to increase readability, some people prefer select/case than if/elseif:
switch(max.length) {
case 6:
answer[0] = 1;
break;
case 5:
answer[0] = 2;
break;
case 4:
answer[0] = 3;
break;
case 3:
answer[0] = 4;
break;
case 2:
answer[0] = 5;
break;
default:
answer[0] = 6;
}
If you want to reduce length, you can just do something like #Bergi said in comment:
answer = [7-max.length, 7-min.length];
But if max and min variable is from user input or from external source, unexpected thing may occurs:
max = {length: -5};
min = {length: -99};
answer = [7-max.length, 7-min.length];
console.log(answer)
// outputs [12,106]
The code may outputs a number outside 1-6 integer range.
So you should also add some Math.max and Math.min if you want your code to behave exactly like your if-elseif statement:
max = {length: -5};
min = {length: -99};
answer = [
Math.max(Math.min(7-max.length,1),6),
Math.max(Math.min(7-min.length,1),6)
];
console.log(answer)
// outputs [6,6]
Of course if you take input from external source you should sanitize/validate it first, but if it's an overkill, you can also use the above Math.min and Math.max function

you need to write just these two lines instead :)
answer[0] = 7 - max.length
answer[1] = 7 - min.length

Related

Effficent way to do sum and maximum of array in javascript

I am working on coding challenge where the scenario is
let arr= [6,-2,9]
For day 1, there are no preceding days' information,
Temperature changes = [6] for the before period.
For succeeding days, there are values [6,-2,5] and 6
The maximum of 6 and 9 is 9.
For day 2, consider [6, -2] -> 6 + (-2) = 4, and [-2, 5] -
(-2) + 5 = 3. The maximum of 3 and 4 is 4.
For day 3, consider [6, -2, 5] -> 6 + (-2)+5=9, and
[5]. The maximum of 9 and 5 is 9.
Temperature changes before and after each day:
Day 1: [-1], [-1, 2, 3] -> max(-1, 4) = 4
Day 2: [-1, 2], [2, 3] -> max(1, 5) =5
Day 3: [-1, 2, 3], [3] -> max(4, 3) = 4
Sum each array and take their maximum.
The maximum from 3 values is [4,5,4] is 5
tempChange = [6, -2, 5]
result
for (let i = 0; i < tempChange.length; i++) {
if (i == 0) {
let sum1 = tempChange[0]
let sum2 = sumArray(tempChange)
if (sum1 > sum2) {
result.push(sum1)
} else {
result.push(sum2)
}
} else if (i == tempChange.length - 1) {
let sum1 = tempChange[tempChange.length]
let sum2 = sumArray(tempChange)
if (sum1 > sum2) {
result.push(sum1)
} else {
result.push(sum2)
}
} else {
let splitArr1 = tempChange.slice(0, i + 1)
let splitArr2 = tempChange.slice(i, tempChange.length + 1)
console.log("a1", splitArr1)
console.log("a2", splitArr2)
let sum1 = sumArray(splitArr1)
let sum2 = sumArray(splitArr2)
if (sum1 > sum2) {
result.push(sum1)
} else {
result.push(sum2)
}
}
}
let finalResult = Math.max(...result)
function sumArray(arr) {
const sum = arr.reduce((partialSum, a) => partialSum + a, 0);
return sum
}
My solution is failing when the array is [ 1000000000, 1000000000, 1000000000, 1000000000, 1000000000, 9999999,9999999]
Time limit exceeded
Allowed time limit:10 secs
Your code did not execute within the time limits. Please optimize your code. For more information on execution time limits, refer to the environment page
Any help will be appreciated
I'm not sure I got the algorithm right from the question, but here's a snippet:
const nums1 = [1000000000, 1000000000, 1000000000, 1000000000, 1000000000, 9999999, 9999999]
const nums2 = [6, -2, 9]
const nums3 = [6, -2, 5]
const nums4 = [-1, 2, 3]
const sum = (arr) => arr.reduce((a, c) => a + c, 0)
const calc = (nums) => nums.reduce((a, c, i, d) => {
const s1 = sum(d.slice(0, i + 1))
const s2 = sum(d.slice(i, d.length))
const max = Math.max(s1, s2)
if (a.max < max) a.max = max
a.change.push(max)
return a
}, {
max: -Infinity,
change: []
})
const nums1Calc = calc(nums1)
console.log(nums1Calc)
const nums2Calc = calc(nums2)
console.log(nums2Calc)
const nums3Calc = calc(nums3)
console.log(nums3Calc)
const nums4Calc = calc(nums4)
console.log(nums4Calc)

How would I write a function that returns all combinations of 3 numbers that equal the target sum WITH RECURSION

What I have so far
let threeSum = (array, targetSum) => {
let newArray = []
if (array.length === 0) {
return newArray
}
for (let i = 0; i < array.length; i++) {
const num1 = array[i];
for (let j = i + 1; j < array.length; j++) {
const num2 = array[j];
for (let k = j + 1; k < array.length; k++) {
const num3 = array[k];
if (num1 + num2 + num3 === targetSum) {
newArray.push([num1, num2, num3])
}
}
}
}
return newArray
}
console.log(threeSum([12, 3, 1, 2, -6, 5, -8, 6], 0))
// [[-8, 2, 6], [-8, 3, 5], [-6, 1, 5]]
This works but only because I'm iterating through the array, I've tried checking the last and first number then slicing the array everytime I recall the function. I've written a base case so far but I'm lost on the recursion step.
This is what I have for the recursion:
let threeSum = (array, targetSum) => {
let newArray = []
if (array.length === 0) {
return newArray
}
let num1 = array[0]
let num2 = array[1]
let num3 = array[2]
if (num1 + num2 + num3 === targetSum) {
newArray.push([num1, num2, num3])
}
return array.slice(1), targetSum
}
console.log(threeSum([12, 3, 1, 2, -6, 5, -8, 6], 0))
// [[-8, 2, 6], [-8, 3, 5], [-6, 1, 5]]
Generators make recursion a bit easier because you can just yield the results. Here the base case is a set of three numbers and a total that equals the values passed in (or no more numbers).
Then just take the first number, add it to found, use it to adjust the total and found numbers and recurse with the rest:
function* threeSum(a, total, found = []) {
if (found.length == 3) {
if (total == 0) yield found
return
}
if (a.length == 0) return
yield* threeSum(a.slice(1), total - a[0], [...found, a[0]])
yield* threeSum(a.slice(1), total, found)
}
console.log([...threeSum([12, 3, 1, 2, -6, 5, -8, 6], 0)])
As pointed out, recursion may not be the best approach, but if you must use it, ...
The idea here is at each level of recursion, you make the problem smaller (by using one of the numbers), and then recurse on the 'rest of the array'.
You stop after 3 numbers are used or you go over the target.
This is called Backtracking.
<div id=divvie> </div>
<script>
var html = "";
var target = 23; // or pass it down
function threesum(subsum, sumsofar, n, Arr, istart)
{
var i;
if (n == 0)
{
if (sumsofar == target)
html += subsum + "<br>";
return;
}
for (i = istart; i < Arr.length; i++)
{
var j = Arr[i];
if (sumsofar + j <= target)
threesum(subsum + "," + j, (sumsofar+j), n-1, Arr, i+1);
}
}
threesum(target + " = ", 0, 3, [8, 5, 2, 6, 9, 7, 4, 1, 12, 3], 0);
document.getElementById("divvie").innerHTML = html;
</script>
Output is:
23 = ,8,6,9
23 = ,8,12,3
23 = ,5,6,12
23 = ,2,9,12
23 = ,7,4,12

Why am I getting wrong results when dividing numbers into arrays with weight percentage?

I have number of users to allocate to number of computers instances like docker or AWS. user can increase the number of instances and also can change the users. The instances have weight percentage.
Users: 10
Locations: 2 [{loc1.weight: 70%}, {loc2.weight: 30%}] so it's simple to have 7 and 3 users for each.
The total percentage might not be equal to hundred so scale factor can be anything.
My other requirement is each instance must have at least 1 user. I have condition applied that minimum user can not be less than locations so that part is good.
Other requirement is all users should be integers.
Example
Case #1
Users: 5
Locations: 4 where 1.weight = 15, 2.weight = 30, 3.weight = 15, 4.weight = 50 (total weight 110%)
Expected Results
Locations:
1.users = 1,
2.users = 1,
3.users = 1,
4.users = 2
Case #2
Users: 10
Locations: 4 where 1.weight = 10, 2.weight = 10, 3.weight = 90, 4.weight = 10 (total weight 120%)
Expected Results
Locations:
1.users = 1,
2.users = 1,
3.users = 7,
4.users = 1
Case #3
Users: 5
Locations: 2 where 1.weight = 50, 2.weight = 50
Expected Results
Locations:
1.users = 3,
2.users = 2
That was all of the explanation of the problem. Below is what I had tried.
function updateUsers(clients, weights) {
let remainingClients = clients;
const maxWeight = weights.reduce((total, weight) => total + parseInt(weight), 0);
let r = [];
weights.forEach(weight => {
let expectedClient = Math.round(clients * (weight / maxWeight));
let val = remainingClients <= expectedClient ? remainingClients : expectedClient;
remainingClients -= expectedClient;
r.push(val > 0 ? val : 1);
});
if ( remainingClients > 0 ) {
r = r.sort((a, b) => a > b ? 1 : -1);
for ( let i = 0; i < remainingClients; i++ ) {
r[i] = r[i] + 1;
}
}
return r;
}
I get good results for some numbers like
updateUsers(12, [5, 5, 5, 90]);
gives
[1, 1, 1, 9]; //total 12 users
but using very odd figures like below
updateUsers(12, [5, 5, 5, 200]);
returns
[2, 1, 1, 11]; //total 15 users which is wrong
At first get percentage, You said that in every quota should at least have 1 user, So we used Math.floor(), If its equal to 0, we return 1 and update userCount like so 1 - percentage.
const sumProcedure = (sum, n) => sum + n;
function updateUsers(userCount, weights) {
let n = userCount,
totalWeight = weights.reduce(sumProcedure),
results = weights.map(weight => {
let percentage = (weight * userCount) / totalWeight,
floor = Math.floor(percentage);
if (floor == 0) {
userCount -= 1 - percentage;
return 1
}
return floor;
}),
remain = n % results.reduce(sumProcedure);
while (remain--) {
let i = weights.indexOf(Math.max(...weights));
weights.splice(i, 1);
results[i]++
}
return results;
}
console.log(updateUsers(5, [50, 50])); // [3 , 2]
console.log(updateUsers(12, [5, 5, 5, 90])); // [1, 1, 1, 9]
console.log(updateUsers(12, [5, 5, 5, 200])); // [1, 1, 1, 9]
console.log(updateUsers(5, [15, 30, 15, 50])); // [ 1, 1, 1, 2 ]
console.log(updateUsers(10, [10, 10, 90, 10])); // [ 1, 1, 7, 1 ]
console.log(updateUsers(55, [5, 5, 5, 90])); // [ 3, 2, 2, 48 ]; It has 2 remainders
This approach works if speed is not super important. I don't know javascript, so a bit of it is going to be in pseudocode. I'll keep your notations though.
Let wSum = sum(weights) be the sum of all weights and unitWeight = wSum / weights.length be the weight each user should be assigned if all were given equal weight. Now, let
r[i] = 1;
weights[i] -= unitWeight;
for i = 0, 1 ... weights.length-1. This ensures that all locations receive at least 1 user and the weights are updated to reflect their 'remaining' weight. Now
remainingClients = clients - weights.length;
Assign the rest of the clients via a while(remainingClients > 0) loop or similar:
while(remainingClients > 0)
{
var indexMax = argMax(weights);
weights[indexMax] -= unitWeight;
r[indexMax] += 1;
remainingClients -= 1;
}
This gives the expected result for all your examples. The argMax should of course just return the index of the array corresponding to the maximum value. Due to argMax, the runtime becomes O(n^2), but it doesn't sound like you have tens of thousands of users, so I hope that's okay.

Javascript Challenge: Loops - Multiple Conditions - stuck and can't figure this out

I did this module on functions and execution context - all questions have gone well but there is one challenge I have spent a lot of time on and still can't figure it out. Any help will be greatly appreciated. Thank you
Challenge question says:
Write a function addingAllTheWeirdStuff which adds the sum of all the odd numbers in array2 to each element under 10 in array1.
Similarly, addingAllTheWeirdStuff should also add the sum of all the even numbers in array2 to those elements over 10 in array1.
BONUS: If any element in array2 is greater than 20, add 1 to every element in array1.
// Uncomment these to check your work!
// console.log(addingAllTheWeirdStuff([1, 3, 5, 17, 15], [1, 2, 3, 4, 5])); // expected log [10, 12, 14, 23, 21]
// console.log(addingAllTheWeirdStuff([1, 3, 5, 17, 15, 1], [1, 2, 3, 4, 5, 22])); // expected log [11, 13, 15, 46, 44, 11]
// my attempt so far:
function addingAllTheWeirdStuff(array1, array2) {
// ADD CODE HERE
let result = []
for (let i = 0; i < array2.length; i++) {
if (array2[i] > 20) {
result = array1[i] += 1
}
}
for (let i = 0; i < array2.length; i++) {
if (array2[i] % 2 === 0 && array1[i] > 10) {
result = array1[i] + array2[i]
}
}
for (let i = 0; i < array2.length; i++) {
if (array2[i] % 2 !== 0 && array1[i] < 10) {
result = array1[i] + array2[i]
}
}
return result
}
You can easily achieve this using reduce and map array method, with the ternary operator:
const array1 = [1, 3, 5, 17, 15];
const array2 = [1, 2, 3, 4, 5];
function addingAllTheWeirdStuff(array1, array2) {
const oddSum = array2.reduce((sum, current) => current % 2 ? current + sum : 0 + sum, 0)
const oddEven = array2.reduce((sum, current) => current % 2 == 0 ? current + sum : 0 + sum, 0)
return array1.map(num => num < 10 ? num + oddSum : num + oddEven)
}
console.log(addingAllTheWeirdStuff(array1, array2))
If you break the challenge into smaller pieces, you can deconstruct it better and come up with your solutions.
This is what I did... I will be adding more comments shortly with more explanations
I chose to keep using loops as I assumed this was the point of the challenges (to practice for loops, multiple conditions, etc) - In other words, I chose to not use map / reduce on purpose but if that's allowed, use the answer by #charmful0x as it results in less code :)
// function to get sum of all odd numbers in array
function getSumOfAllOddNumbersInArray( elementArray ){
var sumOfOddNumbers = 0;
for (let i = 0; i < elementArray.length; i++) {
// use remainder operator to find out if element is odd or not
if (elementArray[i] % 2 !== 0 ) {
sumOfOddNumbers += elementArray[i];
}
}
return sumOfOddNumbers;
}
// function to get sum of all EVEN numbers in array
function getSumOfAllEvenNumbersInArray( elementArray ){
var sumOfEvenNumbers = 0;
for (let i = 0; i < elementArray.length; i++) {
// use remainder operator to find out if element is odd or not
if (elementArray[i] % 2 === 0 ) {
sumOfEvenNumbers += elementArray[i];
}
}
return sumOfEvenNumbers;
}
// Return true if there is at least one element in array that is greater than 20
function hasElementOverTwenty( elementArray ){
for (let i = 0; i < elementArray.length; i++) {
if (elementArray[i] > 20 ) {
// no need to keep looping, we found one - exit function
return true;
}
}
return false;
}
function addingAllTheWeirdStuff( firstArray, secondArray ){
var sumOfOddNumbersInArray = getSumOfAllOddNumbersInArray( secondArray );
var sumOfEvenNumbersInArray = getSumOfAllEvenNumbersInArray( secondArray );
var needToAddOne = hasElementOverTwenty( secondArray );
for (let i = 0; i < firstArray.length; i++) {
// Challenge One
if (firstArray[i] < 10) {
firstArray[i] = firstArray[i] + sumOfOddNumbersInArray;
} else if (firstArray[i] > 10) {
// Challenge Two
firstArray[i] = firstArray[i] + sumOfEvenNumbersInArray;
}
// bonus
if( needToAddOne ){
firstArray[i]++;
}
}
return firstArray;
}
// Uncomment these to check your work!
console.log(addingAllTheWeirdStuff([1, 3, 5, 17, 15], [1, 2, 3, 4, 5]));
console.log('expected:' + [10, 12, 14, 23, 21] );
console.log(addingAllTheWeirdStuff([1, 3, 5, 17, 15, 1], [1, 2, 3, 4, 5, 22]));
console.log('expected:' + [11, 13, 15, 46, 44, 11] );
Challenge question says: Write a function addingAllTheWeirdStuff which adds the sum of all the odd numbers in array2 to each element under 10 in array1.
Similarly, addingAllTheWeirdStuff should also add the sum of all the even numbers in array2 to those elements over 10 in array1.
BONUS: If any element in array2 is greater than 20, add 1 to every element in array1.

How to write the code with less time complexity for finding the missing element in given array range?

My function should return the missing element in a given array range.
So i first sorted the array and checked if the difference between i and i+1 is not equal to 1, i'm returning the missing element.
// Given an array A such that:
// A[0] = 2
// A[1] = 3
// A[2] = 1
// A[3] = 5
// the function should return 4, as it is the missing element.
function solution(A) {
A.sort((a,b) => {
return b<a;
})
var len = A.length;
var missing;
for( var i = 0; i< len; i++){
if( A[i+1] - A[i] >1){
missing = A[i]+1;
}
}
return missing;
}
I did like above, but how to write it more efficiently??
You could use a single loop approach by using a set for missing values.
In the loop, delete each number from the missing set.
If a new minimum value is found, all numbers who are missing are added to the set of missing numbers, except the minimum, as well as for a new maximum numbers.
The missing numbers set contains at the end the result.
function getMissing(array) {
var min = array[0],
max = array[0],
missing = new Set;
array.forEach(v => {
if (missing.delete(v)) return; // if value found for delete return
if (v < min) while (v < --min) missing.add(min); // add missing min values
if (v > max) while (v > ++max) missing.add(max); // add missing max values
});
return missing.values().next().value; // take the first missing value
}
console.log(getMissing([2, 3, 1, 5]));
console.log(getMissing([2, 3, 1, 5, 4, 6, 7, 9, 10]));
console.log(getMissing([3, 4, 5, 6, 8]));
Well, from the question (as it's supposed to return a single number) and all the existing solution (examples at least), it looks like list is unique. For that case I think we can sumthe entire array and then subtracting with the expected sum between those numbers will generate the output.
sum of the N natural numbers
1 + 2 + ....... + i + ... + n we can evaluate by n * (n+1) / 2
now assume, in our array min is i and max is n
so to evaluate i + (i+1) + ..... + n we can
A = 1 + 2 + ..... + (i-1) + i + (i+1) + .... n (i.e. n*(n+1)/2)
B = 1 + 2 + ..... + (i-1)
and
C = A - B will give us the sum of (i + (i+1) + ... + n)
Now, we can iterate the array once and evaluate the actual sum (assume D), and C - D will give us the missing number.
Let's create the same with each step at first (not optimal for performance, but more readable) then we will try to do in a single iteration
let input1 = [2, 3, 1, 5],
input2 = [2, 3, 1, 5, 4, 6, 7, 9, 10],
input3 = [3, 4, 5, 6, 8];
let sumNatural = n => n * (n + 1) / 2;
function findMissing(array) {
let min = Math.min(...array),
max = Math.max(...array),
sum = array.reduce((a,b) => a+b),
expectedSum = sumNatural(max) - sumNatural(min - 1);
return expectedSum - sum;
}
console.log('Missing in Input1: ', findMissing(input1));
console.log('Missing in Input2: ', findMissing(input2));
console.log('Missing in Input3: ', findMissing(input3));
Now, lets try doing all in a single iteration (as we were iterating 3 times for max, min and sum)
let input1 = [2, 3, 1, 5],
input2 = [2, 3, 1, 5, 4, 6, 7, 9, 10],
input3 = [3, 4, 5, 6, 8];
let sumNatural = n => n * (n + 1) / 2;
function findMissing(array) {
let min = array[0],
max = min,
sum = min,
expectedSum;
// assuming the array length will be minimum 2
// in order to have a missing number
for(let idx = 1;idx < array.length; idx++) {
let each = array[idx];
min = Math.min(each, min); // or each < min ? each : min;
max = Math.max(each, max); // or each > max ? each : max;
sum+=each;
}
expectedSum = sumNatural(max) - sumNatural(min - 1);
return expectedSum - sum;
}
console.log('Missing in Input1: ', findMissing(input1));
console.log('Missing in Input2: ', findMissing(input2));
console.log('Missing in Input3: ', findMissing(input3));
Instead of sorting, you could put each value into a Set, find the minimum, and then iterate starting from the minimum, checking if the set has the number in question, O(N). (Sets have guaranteed O(1) lookup time)
const input1 = [2, 3, 1, 5];
const input2 = [2, 3, 1, 5, 4, 6, 7, 9, 10];
const input3 = [3, 4, 5, 6, 8];
function findMissing(arr) {
const min = Math.min(...arr);
const set = new Set(arr);
return Array.from(
{ length: set.size },
(_, i) => i + min
).find(numToFind => !set.has(numToFind));
}
console.log(findMissing(input1));
console.log(findMissing(input2));
console.log(findMissing(input3));
If the array is items and the difference between missing and present diff is 1:
const missingItem = items => [Math.min(...items)].map(min => items.filter(x =>
items.indexOf(x-diff) === -1 && x !== min)[0]-diff)[0]
would give complexity of O(n^2).
It translates to: find the minimum value and check if there isn't a n-diff value member for every value n in the array, which is also not the minimum value. It should be true for any missing items of size diff.
To find more than 1 missing element:
([Math.min(...items)].map(min => items.filter(x =>
items.indexOf(x-diff) === -1 && x !== min))[0]).map(x => x-diff)
would give O((m^2)(n^2)) where m is the number of missing members.
Found this old question and wanted to take a stab at it. I had a similar thought to https://stackoverflow.com/users/2398764/koushik-chatterjee in that I think you can optimize this by knowing that there's always only going to be one missing element. Using similar methodology but not using a max will result in this:
function getMissing(arr) {
var sum = arr.reduce((a, b) => a + b, 0);
var lowest = Math.min(...arr);
var realSum = (arr.length) * (arr.length + 1) / 2 + lowest * arr.length;
return realSum - sum + lowest;
}
With the same inputs as above. I ran it in jsperf on a few browsers and it is faster then the other answers.
https://jsperf.com/do-calculation-instead-of-adding-or-removing.
First sum everything, then calculate the lowest and calculate what the sum would be for integers if that happened to be the lowest. So for instance if we have 2,3,4,5 and want to sum them that's the same as summing 0,1,2,3 and then adding the lowest number + the amount of numbers in this case 2 * 4 since (0+2),(1+2),(2+2),(3+2) turns it back into the original. After that we can calculate the difference but then have to increase it once again by the lowest. To offset the shift we did.
You can use while loop as well, like below -
function getMissing(array) {
var tempMin = Math.min(...array);
var tempMax = tempMin + array.length;
var missingNumber = 0;
while(tempMin <= tempMax){
if(array.indexOf(tempMin) === -1) {
missingNumber = tempMin;
}
tempMin++;
}
return missingNumber;
}
console.log(getMissing([2, 3, 1, 5]));
console.log(getMissing([2, 3, 1, 5, 4, 6, 7, 9, 10]));
console.log(getMissing([3, 4, 5, 6, 8]));
My approach is based on in place sorting of the array which is O(N) and without using any other data structure.
Find the min element in the array.
Sort in place.
Again loop the array and check if any element is misplaced, that is the answer!
function getMissing(ar) {
var mn = Math.min(...ar);
var size = ar.length;
for(let i=0;i<size;i++){
let cur = ar[i];
// this ensures each element is in its right place
while(cur != mn +i && (cur - mn < size) && cur != ar[cur- mn]) {
// swap
var tmp = cur;
ar[i] = ar[cur-mn];
ar[cur-mn] = tmp;
}
}
for(let i=0; i<size; i++) {
if(ar[i] != i+mn) return i+mn;
}
}
console.log(getMissing([2, 3, 1, 5]));
console.log(getMissing([2, 3, 1, 5, 4, 6, 7, 9, 10]));
console.log(getMissing([3, 4, 5, 6, 8]));

Categories

Resources