Why is my for loop breaking earlier than expected? - javascript

I am trying to solve a problem on leetCode:
Given an unsorted integer array nums, return the smallest missing positive integer.
This is the code I came up with
var firstMissingPositive = function(nums) {
nums.sort();
let x = 1; //this is to compare the elements of nums
for (let num in nums) {
if (nums[num] <= 0) continue; //because anything less than 1 does not matter
else if (nums[num] != x) break; //if x is not present, x is the answer
else x++; // if x is present, x should increment and check for the next integer
}
return x;
};
This code works 106/173 testcases. It does not pass the following case, which looks very simple -
nums = [1,2,3,4,5,6,7,8,9,20];
The output I get is 3, whereas the expected output is 10.
I'm not looking for the right solution to the problem. I'm just curious why this seemingly simple test fails. I do not understand why my loop breaks at 3 when it passes 1 and 2. Please help!

Here's the root cause of your problem (mdn):
The sort() method sorts the elements of an array in place and returns
the sorted array. The default sort order is ascending, built upon
converting the elements into strings, then comparing their sequences
of UTF-16 code units values.
So what you get after sort is [1, 2, 20, 3, ...], as '20' string precedes '3' string. One possible way to fix this it to force sorting by numeric value:
nums.sort((a, b) => a - b);

Related

How to add every combination of numbers in an array

I'm taking in an array of numbers [4, 6, 23, 10, 1, 3] I need to return true if any combinations of numbers in the array add up to the largest number in the array. So the example above should return true because 3 + 4 + 6 + 10 = 23
My thought behind this problem is I should first put the array in numerical order then make a new array with just the numbers I'm adding because I'm not adding the largest number. Then I need some method that says "If any combination of adding these numbers together equals the largest number in the original array return true". This is the code I've written so far, but I'm stuck on the for loop.. Any help would be very much appreciated!
function ArrayChallenge(arr){
let order = arr.sort(function(a, b){return a-b})
let addThese = order.slice(0,order.length-1)
for(i = 0; i < addThese.length-1; i++){
return true
}
}
console.log(ArrayChallenge([3,5,-1,8,12]))
It seems like a trick question. Here's the answer:
function ArrayChallenge(arr){
return true
}
Because the sum of just the largest number is always equal to the largest number.
If this solution is somehow not allowed, see subset sum problem:
there is a multiset S of integers and a target-sum T, and the question is to decide whether any subset of the integers sum to precisely T.
The most straightforward solution to that problem is with recursion; something like this:
function subsetSum(arr, sum) {
if (arr.length == 0) {
// No numbers left in the array. The only sum we can make is 0.
// If that is the sum we are seeking, great!
return sum == 0
} else {
// We will try both using and not using the first number in the array.
// The rest is passed to the recursive call.
const [current, ...remaining] = arr
return (
// Exclude current number, and recurse. We have to make the full
// sum with the remaining numbers.
subsetSum(remaining, sum) ||
// Include current number, meaning we have sum - current left
// to make with the remaining numbers.
subsetSum(remaining, sum - current)
)
}
}

Two-sum Leetcode explanation, Hashmap, Javascript

Im just wondering who can explain the algorithm of this solution step by step. I dont know how hashmap works. Can you also give a basic examples using a hashmap for me to understand this algorithm. Thank you!
var twoSum = function(nums, target) {
let hash = {};
for(let i = 0; i < nums.length; i++) {
const n = nums[i];
if(hash[target - n] !== undefined) {
return [hash[target - n], i];
}
hash[n] = i;
}
return [];
}
Your code takes an array of numbers and a target number/sum. It then returns the indexes in the array for two numbers which add up to the target number/sum.
Consider an array of numbers such as [1, 2, 3] and a target of 5. Your task is to find the two numbers in this array which add to 5. One way you can approach this problem is by looping over each number in your array and asking yourself "Is there a number (which I have already seen in my array) which I can add to the current number to get my target sum?".
Well, if we loop over the example array of [1, 2, 3] we first start at index 0 with the number 1. Currently, there are no numbers which we have already seen that we can add with 1 to get our target of 5 as we haven't looped over any numbers yet.
So, so far, we have met the number 1, which was at index 0. This is stored in the hashmap (ie object) as {'1': 0}. Where the key is the number and the value (0) is the index it was seen at. The purpose of the object is to store the numbers we have seen and the indexes they appear at.
Next, the loop continues to index 1, with the current number being 2. We can now ask ourselves the question: Is there a number which I have already seen in my array that I can add to my current number of 2 to get the target sum of 5. The amount needed to add to the current number to get to the target can be obtained by doing target-currentNumber. In this case, we are currently on 2, so we need to add 3 to get to our target sum of 5. Using the hashmap/object, we can check if we have already seen the number 3. To do this, we can try and access the object 3 key by doing obj[target-currentNumber]. Currently, our object only has the key of '1', so when we try and access the 3 key you'll get undefined. This means we haven't seen the number 3 yet, so, as of now, there isn't anything we can add to 2 to get our target sum.
So now our object/hashmap looks like {'1': 0, '2': 1}, as we have seen the number 1 which was at index 0, and we have seen the number 2 which was at index 1.
Finally, we reach the last number in your array which is at index 2. Index 2 of the array holds the number 3. Now again, we ask ourselves the question: Is there a number we have already seen which we can add to 3 (our current number) to get the target sum?. The number we need to add to 3 to get our target number of 5 is 2 (obtained by doing target-currentNumber). We can now check our object to see if we have already seen a number 2 in the array. To do so we can use obj[target-currentNumber] to get the value stored at the key 2, which stores the index of 1. This means that the number 2 does exist in the array, and so we can add it to 3 to reach our target. Since the value was in the object, we can now return our findings. That being the index of where the seen number occurred, and the index of the current number.
In general, the object is used to keep track of all the previously seen numbers in your array and keep a value of the index at which the number was seen at.
Here is an example of running your code. It returns [1, 2], as the numbers at indexes 1 and 2 can be added together to give the target sum of 5:
const twoSum = function(nums, target) {
const hash = {}; // Stores seen numbers: {seenNumber: indexItOccurred}
for (let i = 0; i < nums.length; i++) { // loop through all numbers
const n = nums[i]; // grab the current number `n`.
if (hash[target - n] !== undefined) { // check if the number we need to add to `n` to reach our target has been seen:
return [hash[target - n], i]; // grab the index of the seen number, and the index of the current number
}
hash[n] = i; // update our hash to include the. number we just saw along with its index.
}
return []; // If no numbers add up to equal the `target`, we can return an empty array
}
console.log(twoSum([1, 2, 3], 5)); // [1, 2]
A solution like this might seem over-engineered. You might be wondering why you can't just look at one number in the array, and then look at all the other numbers and see if you come across a number that adds up to equal the target. A solution like that would work perfectly fine, however, it's not very efficient. If you had N numbers in your array, in the worst case (where no two numbers add up to equal your target) you would need to loop through all of these N numbers - that means you would do N iterations. However, for each iteration where you look at a singular number, you would then need to look at each other number using a inner loop. This would mean that for each iteration of your outer loop you would do N iterations of your inner loop. This would result in you doing N*N or N2 work (O(N2) work). Unlike this approach, the solution described in the first half of this answer only needs to do N iterations over the entire array. Using the object, we can find whether or not a number is in the object in constant (O(1)) time, which means that the total work for the above algorithm is only O(N).
For further information about how objects work, you can read about bracket notation and other property accessor methods here.
You may want to check out this method, it worked so well for me and I have written a lot of comments on it to help even a beginner understand better.
let nums = [2, 7, 11, 15];
let target = 9;
function twoSums(arr, t){
let num1;
//create the variable for the first number
let num2;
//create the variable for the second number
let index1;
//create the variable for the index of the first number
let index2;
//create the variable for the index of the second number
for(let i = 0; i < arr.length; i++){
//make a for loop to loop through the array elements
num1 = arr[i];
//assign the array iteration, i, value to the num1 variable
//eg: num1 = arr[0] which is 2
num2 = t - num1;
//get the difference between the target and the number in num1.
//eg: t(9) - num1(2) = 7;
if(arr.includes(num2)){
//check to see if the num2 number, 7, is contained in the array;
index1 = arr.indexOf(num2);
//if yes get the index of the num2 value, 7, from the array,
// eg: the index of 7 in the array is 1;
index2 = arr.indexOf(num1)
//get the index of the num1 value, which is 2, theindex of 2 in the array is 0;
}
}
return(`[${index1}, ${index2}]`);
//return the indexes in block parenthesis. You may choose to create an array and push the values into it, but consider space complexities.
}
console.log(twoSums(nums, target));
//call the function. Remeber we already declared the values at the top already.
//In my opinion, this method is best, it considers both time complexity and space complexityat its lowest value.
//Time complexity: 0(n)
function twoSum(numbers, target) {
for (let i = 0; i < numbers.length; i++) {
for (let j = i + 1; j < numbers.length; j++) {
if (numbers[i] + numbers[j] === target) {
return [numbers.indexOf(numbers[i]), numbers.lastIndexOf(numbers[j])];
}
}
}
}

Javascript find the highest value in 2d array based on array itself

I've a multidimensional array
arr = [[[1,1],[2,1],[3,1],[4,2],[5,2],[6,2],[7,3],[8,4]],
[[1,1],[2,1],[3,1],[4,3],[5,3],[6,4],[7,4],[8,5],[9,5],[10,5]]
];
and so on ... but the dimension of the arr is not fixed, is variable.
I've a variable that tell me where to point my attention
var number = 2;
So my goal is the look in any arr[i] and find the max 1st argument based on the 2nd argument, I try to explain better my self, in this particular case if number is 2 my expectation is to have from arr:
for the 1st array in arr -> 6 (because the second argument is 1,1,1,2,2,2,3 so I've to point at the last 2 and return the 1st argument)
for the 2nd array in arr -> 3 (because 2 is missing and the 1 is the last second argument)
I know is a little tricky
My first idea was to make a for loops where I delete all value over my number, then I can take the very last one, but I think I'm over-complicating all.
There is a better and fast way to achieve the same result?
J
You present lists (arrays) of pairs of numbers, where the pairs are sorted in ascending order, first by the second number, then by the first.
What you seem to ask for is: Given a number to search for among the second numbers, e.g. number = 2, find the last pair where the second number is less than or equal to this number, and return the corresponding first number in this pair.
You state that you could use for loops to solve the problem. A straightforward approach could be like the following snippet:
var arr = [[[1,1],[2,1],[3,1],[4,2],[5,2],[6,2],[7,3],[8,4]],
[[1,1],[2,1],[3,1],[4,3],[5,3],[6,4],[7,4],[8,5],[9,5],[10,5]]
];
var findNumber = 2;
var result = [];
for(var i = 0; i < arr.length; i++){
var maxIndex = -1;
for(var j = 0;
j < arr[i].length && arr[i][j][1] <= findNumber;
j++){
maxIndex = j;
}
result.push(arr[i][maxIndex][0]);
}
//gives the expected answers 6 and 3
console.log(result);
Then you ask:
There is a better and fast way to achieve the same result?
A solution involving .map and .reduce could be considered more elegant, like the following:
var arr = [[[1,1],[2,1],[3,1],[4,2],[5,2],[6,2],[7,3],[8,4]],
[[1,1],[2,1],[3,1],[4,3],[5,3],[6,4],[7,4],[8,5],[9,5],[10,5]]
];
var findNumber = 2;
var result = arr.map(function(val){
return val[val.reduce(function(acc, curr, index){
return curr[1] <= findNumber? index : acc;
}, -1)][0];
});
//gives the expected answers 6 and 3
console.log(result);
However, in terms of performance, for loops are likely to perform better (run faster) and are easy to comprehend.
In addition, you mention that
the dimension of the arr is not fixed
You would need to post some code examples on how the dimensionality of your data may vary before it would be possible to provide any answer that handles this aspect.
Update
To handle a single array of pairs, you do not need the outer loop or .map(). Putting the solution above into a reusable function:
function lookupFirstNumberFromSecond(secondNumberToFind, arr){
var j = 0, maxIndex = -1;
while(j < arr.length && arr[j][1] <= secondNumberToFind){
maxIndex = j++;
}
return arr[maxIndex][0];
}
//gives the expected answer 6
console.log(lookupFirstNumberFromSecond(
2,
[[1,1],[2,1],[3,1],[4,2],[5,2],[6,2],[7,3],[8,4]]
));
//gives the expected answer 3
console.log(lookupFirstNumberFromSecond(
2,
[[1,1],[2,1],[3,1],[4,3],[5,3],[6,4],[7,4],[8,5],[9,5],[10,5]]
));
I'm not entirely sure about what you are trying to achieve but I guess Array.reduce is a pretty elegant solution to get a single value out of an array.
e.g.
var number = 2;
[[1,4],[2,1],[3,1],[4,2],[5,2],[6,2],[7,3],[8,4]]
.reduce(function (a, b) {
return ((!a || b[0] > a[0]) && b[1] === number) ? b : a;
});
Not entirely sure what you're trying to solve either, but if you're trying to get the max value in a n dimensional array, then the most straightforward method is to solve this standardly in a recursive manner
function recurseMax(arr) {
if (Number.isInteger(arr)) {
return arr;
}
else {
answer = 0;
for (let i = 0; i < arr.length; i++) {
answer = answer > recurseMax(arr[i]) ? answer : recurseMax(arr[i]);
}
return answer;
}
}
console.log(recurseMax([1,[3, 5], [5, 6, 7, 10], [2, [3, [500]]]])); //Outputs 500
For each element, either is a number or another possible multidimensional element, so we recursively find its max. This avoids potential overhead from a reduce operation (though I'm not experienced enough to speak with confidence whether or not it is completely faster, not really sure of the optimizations V8 can do on reduce or a plain old recursion loop). Either way, the solution is fairly straightforward.
I am answering the question based on the assumption that you mean that the array can have a max dimension of n.

Javascript reduce function/ternary operator

function largestInEach(arr) {
var resultArray = [],
highestValue = 0;
for (var i = 0; i < arr.length; i++) {
highestValue = arr[i].reduce(function(a, b){
return a >= b ? a : b;
});
resultArray.push(highestValue);
}
return resultArray;
}
Can someone please explain this code.
The rest of the code is very clear to me, but I have difficulty understanding the reduce function and its application.
I agree with most of the other comments that you should search more and do self learning.
However, I know it is sometimes hard to find the exact info on how things work. So ill explain this to you.
Now coming to your code.
https://jsfiddle.net/Peripona/ppd4L9Lz/
It contains an array of arrays where you at the end create a resulted array with highest or lowest value elements from all the sub arrays.
like you got
var arry = [[1,2,3],[2,3,4],[20,-2,3]]
talking in layman terms...
you got one array if you sort or reduce an array of integers, it might not always generate what you
say for example if you got this data
var ar = [1,3,34,11,0,13,7,17,-2,20,-21]
and if you do normal ar.sort() to get the sorted values
you would expect something like this... as output
" [-21, -2, 0, 1, 3, 7, 11, 13, 17, 20, 34] "
but on the contrary you would get the output like this..
" [-2, -21, 0, 1, 11, 13, 17, 20, 3, 34, 7] "
Now you wonder... why this strange behavior and how does it matter anyhow to my Question..
It Does matter..
Cuz this is what you need to do to get the right output..
The way sort function is written has to work for for String and other types as well. so they convert data into other formats when doing comparison on sort.
So all in all if you pass a function inside and specify that you need the in ascending order that is a-b..
Descending order that is b-a..
ar.sort(function(a,b){return a-b;})
Now coming to another part that is Reduce this function takes a function argument and get you the highest or the lowest value from the array.
therefore if you do..
ar.reduce(function(a,b){return a>=b ? b : a})
will give you -21 as the output..
and if you do
ar.reduce(function(a,b){return a>=b ? a : b})
It will give you : 34
So this function will take multidimensional arrays where each array contains some digits and this function will get you the highest from all those arrays..
I hope this Explains everything.
Reduce function allows you to go through each item in an array, where you will be able to see previous array value, and current array value, in your case:
a = previous value,
b = current value,
-(not in there)-
i = index,
currArray = the array you are working with.
and in your code you are comparing and returning if your previous value is greater than or equal to current value.
a >= b ? a : b;
Conditional (ternary) Operator which is (condition ? do this : or this ) -> Think of it like a if statement
If(a >= b){
return a
}else{
return b
}
see Conditional (ternary) Operator
Also your 'arr' could be multi dimensional array. forexample Trying the following code on http://plnkr.co/edit/?p=preview
hit f12 for developer tools and look at console for results.
var arr = [[1,2],[4,3],[5,23,52]];
var resultArray = [],
var highestValue;
for (var i = 0; i < arr.length; i++) {
highestValue = arr[i].reduce(function(a, b){
return a >= b ? a : b;
});
resultArray.push(highestValue);
}
console.log(resultArray);
You result array contains [2, 4, 52].
I hope this helps.
JS reduce method is applied against two values of array and reduce these two values of array ( a and b) into one (c) based on defined condition (return c = a+b ).
Here in your case the condition was which among two is greater (a>b?a:b).

javascript - map one array to a second array with a negative index offset

Alright, I'm taking an array, and making another array from it with the only difference being the indexes are displaced by an arbitrary number determined using two reference points (one in each array). Doing this creates negative indexes, which if it didn't stop the script from working, would be useful. Is there any way to have the second array have the negative indexes and work, or am I going to have to use an all-together different method? I rewrote the code to be a simple case.
var firstArray = {
field: [ 1, 2, 3, 4, 5],
referenceIndex : 2
};
var secondArray = {
referenceIndex: 1,
offset: 0,
field : {}
};
// Create secondArray.field by finding the offset.
secondArray.offset = firstArray.referenceIndex - secondArray.referenceIndex;
for (i=0; i < firstArray.field.length; i++){
alert([i - secondArray.offset, firstArray.field[i]].join(" "));
secondArray.field[i - secondArray.offset] = firstArray.field[i]; //creates a negative index.
}
An array can have (in a strict sense) only positive integer as indices. However it is also an object, so it can take any string as a property. So in a sense, it will 'work', but do not trust Array#length to have the right value.
var arr = [1,2,3];
arr.length //3
arr[10] = 10;
arr.length //11
arr["blah"] = 100;
arr.length //still 11
arr[-1] = 200;
arr.length //still 11
I'd also like to point you to this excellent article - http://javascriptweblog.wordpress.com/2010/07/12/understanding-javascript-arrays/
No you can't have negative indices and have it work properly, however, you possibly could save a number and add it to your index to create a positive value. For example you have indeces -2 through 4. In the array this would be 0 - 6 so you would need to add or subtract 2 to get to the value of the index you want.

Categories