I am trying to write a function that returns the first two values in order of appearance that add to the sum. My function works fine with positive numbers, but not with negative. Can anyone tell me what I am doing wrong?
This function return an empty array:
const sumOfPairs = (arr, sum) => {
const answer = [];
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr.length; j++) {
if (arr[i] + arr[j] === sum && i != j) {
answer.push(arr[j], arr[i]);
}
break;
}
}
return answer;
}
console.log(sumOfPairs([1, -2, 3, 0, -6, 1], -6));
Your implementation doesn't work for all positive numbers either. Try 3 as sum.
I believe you want to put the break statement inside the if statement or just replace the body of the if statement with return [arr[j], arr[i]]:
const sumOfPairs = (arr, sum) => {
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr.length; j++) {
if (arr[i] + arr[j] === sum && i != j) {
// You can return here if you only want to find *one* pair
// You also need add some additional logic if you want them
// to be in the same order as in the original array:
return i < j ? [arr[i], arr[j]] : [arr[j], arr[i]]
}
}
}
return []
}
console.log(sumOfPairs([1, -2, 3, 0, -6, 1], -6));
The current location of the break statement in your loop causes the inner loop to terminate after its first iteration! Therefore the inner loop is equivalent to testing whether the sum of the current outer loop's item (arr[i]) and 1 (the first element in the array) is equal the provided sum.
Related
I am trying to solve a problem , Two Sum for those who know it , I started learning JavaScript coming from Lua , and I am stuck , I don't know why the function returns "undefined" I fill like the variable is defined
var num = [2, 7, 11, 15]
function numbers(target) {
var idx = {}
num.forEach(function(n, i) {
var j = idx[target - n]
if (j) {
var res = '[ ${j} ${i} ]'
return res
}
console.log(n)
idx[n] = i
})
}
console.log(numbers(9))
output:
2
7
11
15
undefined
Problem: https://leetcode.com/problems/two-sum/
I found the solution I think , I don't think it's the best one , but it works
Code:
var nums = [2,7,11,15]
var twoSum = function(target) {
for (let i = 0; i < nums.length; i++) {
for (let j = i + 1; j < nums.length; j++) {
if (nums[i] + nums[j] == target) {
return [i, j]
}
}
}
}
console.log(twoSum(9))
You have a few issues:
Your current code is returning a string '[ ${j} ${i} ]', you need to return an array [j, i].
Using return from within .forEach() does not return from your numbers function, it instead returns from the inner callback function function(n, i) { which doesn't do much except just skips to the next item in the loop. You need to change your forEach() to a regular for loop so that when you return you return from your numbers function, and not an inner callback.
Your condition if (j) { is flawed. Consider if j is 0, which occurs when the number you're after to add to the current number n is at index 0. In this case, your if-block won't run because 0 is considered falsy. Your condition should instead be more specific by checking that it returned a value if(j !== undefined). See this answer for more details about the condition.
You should be passing nums into your numbers() function rather than relying on a global variable to exist for your function to work correctly.
Example of modified code:
function numbers(nums, target) {
const idx = {}
for(let i = 0; i < nums.length; i++) {
let n = nums[i];
let j = idx[target - n]
if (j !== undefined) {
return [j, i];
}
idx[n] = i;
}
}
console.log(numbers([2, 7, 11, 15], 9));
console.log(numbers([3,2,4], 6));
console.log(numbers([3,3], 6));
See the answers for this question for more details for solving this problem.
var twoSum = function(nums, target) {
let newArr = nums
let sum = 0
outputArr = []
for(let i = 0 ; i < nums.length ; i++){
let val1 = nums[i]
for(let j = 0 ; j < newArr.length ; j++){
if(i !==j) {
let val2 = newArr[j]
if(val1 + val2 === target) {
sum = val1 + val2
outputArr.push(i)
outputArr.push(j)
break;
}
}
}
if(sum === target)
break;
}
return outputArr
};
try this If helps and you need explanation I will help you
I am trying to check for matching instances of arrays within a larger array. To do this, I am implementing a condition where if two of three numbers in an array match two of the three members of any of the arrays within a larger array, there is a continue statement to go back to a previous loop:
var threeSum = function (nums) {
let result = [];
for (let i = 0; i < nums.length - 2; i++) {
for (let j = i + 1; j < nums.length - 1; j++) {
loop1: for (let k = j + 1; k < nums.length; k++) {
if (nums[i] + nums[j] + nums[k] === 0) {
let smallArray = [nums[i], nums[j], nums[k]].sort((a, b) => a - b);
for (let l = 0; l < smallArray.length && result[l]; l++) {
if (
smallArray[0] == result[l][0] &&
smallArray[1] == result[l][2]
) {
console.log("we already have this array")
continue loop1;
}
}
result.push(smallArray);
}
}
}
}
return result;
};
Thus, for example threeSum([-1, 0, 1, 2, -1, -4]) should return [[-1, 0, 1], [-1, -1, 2]] when is instead is returning [[-1, 0, 1], [-1, -1, 2], [-1, 0, 1]]. I have checked using the console.log in the inner most conditional, and the if statement is never returning as true, so it is never entering the continue command. But the first and third arrays should meet the requirements of this, so it seems as if when checking the third array, the function should kick back the command.
I am a bit puzzled as to what is going wrong.
A single loop approach but with recursion and filtering for arrays with same values.
function threeSum(array, temp = [], sum = 0, i = 0) {
if (temp.length === 3) return sum ? [] : [temp];
const result = [];
while (i < array.length) {
result.push(...threeSum(array, [...temp, array[i]], sum + array[i], ++i));
}
return result.filter((s => a => (b => !s.has(b) && s.add(b))([...a].sort().join('|')))(new Set));
}
console.log(threeSum([-1, 0, 1, 2, -1, -4]));
I solved this problem by iterating through the array then find the item when the sum equals to array[i] + item returning true otherwise returning false.
My Question is => How I can return the indices of those numbers that add up to sum not just true? Using the same code below:
function hasPairsWithSum(array,sum) {
for (let i = 0; i < array.length; i++) {
if (array.find((item) => {return sum === array[i] + item}
));
return true;
};
return false;
};
console.log(hasPairsWithSum([1,2,4,4],8))
Note: Time complexity must be less than O(n ^ 2).
JavaScript O(n) Solution.
function hasPairsWithSum(array, sum) {
const map = new Map ();
for(let i = 0; i < array.length; i++) {
let currVal = array[i];
if (map.has(currVal)) {
return [map.get(currVal),i]
}
// difference value = sum - current value
let diff = sum - currVal
map.set(diff,i)
}
};
console.log(hasPairsWithSum([2,2,4,4], 8))
Please refer this code.
function hasPairsWithSum(array,sum) {
let result = [];
for (let i = 0; i < array.length; i++) {
if (array.some((item, index) => {return i === index ? false : sum === array[i] + item}))
result.push(i);
};
return result;
};
console.log(hasPairsWithSum([1,2,4,4],8))
console.log(hasPairsWithSum([3,2,4],6))
console.log(hasPairsWithSum([0,4,3,0],0))
O(n) Soln ... using math concept a+b = n then if a is present in our array then need to find b = n - a is present or not ..
def hasPairsWithSum(array,sum):
d = {}
for i in range(len(array)):
if(array[i] in d):
d[array[i]].append(i)
else:
d[array[i]] = [i]
ans = []
for i in range(len(array)):
val = sum - array[i]
if(val in d):
if(d[val][0] == i):
if(len(d[val]) > 1):
ans.append((i,d[val][1]))
break
else:
continue
else:
ans.append((i,d[val][0]))
break
return ans
print(hasPairsWithSum([4, 4, 4, 4], 8))
O(nlogn) soln ....just store the index with elements .. then sort it by their values .. next step run a loop with complexity of O(n) [concept : Two pointers]
def hasPairsWithSum(array,sum):
arr = []
for i in range(len(array)):
arr.append((array[i],i))
arr.sort()
i = 0
j = len(array)-1
ans = []
while(i<j):
tmp_sum = arr[i][0] + arr[j][0]
if(tmp_sum == sum):
ans.append((arr[i][1] , arr[j][1]))
#add your logic if you want to find all possible indexes instead of break
break
elif(tmp_sum < sum):
i = i + 1
elif(tmp_sum > sum):
j = j - 1
return ans
print(hasPairsWithSum([1,2,4,4],8))
note : if you want to find all possible soln then these approaches will not work either add you own logic in while loop or another approach is use binary search with traversal on every element and store the indexes in set (worst case this will be O(n^2) as we have to find all possible values) Eg: [4,4,4,4,4,4] , sum = 8 and you want to print all possible indexes then we end up running it upto n^2 (why? reason: total possible solns. are 5+4+3+2+1 = n*(n-1)/2 ≈ n^2)
You have to iterate over the array elements checking at every iteration for every element of the array (except the last one) all the elements at the right of it like below:
function findIndexes(array, sum) {
const result = [];
for (let i = 0; i < array.length -1; ++i) {
for (let j = i + 1; j < array.length; ++j) {
if ((array[i] + array[j]) === sum) {
result.push([i, j]);
}
}
}
return result;
}
console.log(findIndexes([1, 2, 4, 4], 8));
console.log(findIndexes([3, 2, 4], 6));
Update:
It is possible to obtain a linear O(n) complexity using an auxiliary Map structure associating an integer value as key with as a value the list containing all the indexes of the elements in the array equal to the integer key like below:
function findIndexes(array, sum) {
const map = new Map();
const result = [];
for (let i = 0; i < array.length; ++i) {
const a = array[i];
const b = sum - a;
if (map.has(b)) {
for (const index of map.get(b)) {
result.push([index, i]);
}
}
const l = map.has(a) ? map.get(a) : [];
l.push(i);
map.set(a, l);
}
return result;
}
console.log(findIndexes([1, 2, 4, 4], 8));
console.log(findIndexes([3, 2, 4], 6));
console.log(findIndexes([1, 1, 1], 2));
I've got working code, but I'm looking to improve the way I understand and implement different coding techniques as a whole. I thought this problem presented a good chance to get feedback on what I'm doing.
The idea here is to take two arguments, an array and an integer. Identify all pairs in the array that sum to make the integer argument, and then return the sum of the indices. You cannot reuse an index, and you must always use the smallest index available to you. There is an explanation on the FCC code guide here: https://www.freecodecamp.org/learn/coding-interview-prep/algorithms/pairwise
So - here is the question. Is there any good way of doing this without using nested for loops? I am becoming increasingly aware of time/space complexities, and I know that O(n^2) won't land me the job.
I would imagine a hashmap of some sort would come into it, but I just don't have the experience and knowledge to know how to use them.
Here is the code:
function pairwise(arr, arg) {
let usedIndex = [];
let output = 0;
for (let i = 0; i < arr.length; i++) {
for (let j = i + 1; j < arr.length; j++) {
if (
arr[i] + arr[j] == arg
&& usedIndex.indexOf(i) == -1
&& usedIndex.indexOf(j) == -1
) {
usedIndex.push(i, j)
output += i + j
}
}
}
return output;
}
pairwise([0, 0, 0, 0, 1, 1], 1) // should return 10
This can be done in one loop with some clever use of an object and knowledge that indices can only be used once.
function pairwise(arr, arg) {
let map = {};
let output = 0;
let length = arr.length;
for (let i = 0; i < length; i++) {
let subArr = map[arr[i]];
if(subArr && subArr[0] !== undefined) {
//there is an index waiting to pair, remove it and add to output
output += subArr.pop() + i;
} else {
//add this index to its pair slot
let left = arg - arr[i];
if(!map[left]) map[left] = [];
map[left].unshift(i);
}
}
return output;
}
console.log(pairwise([0, 0, 0, 0, 1, 1], 1), "should be 10");
console.log(pairwise([1, 4, 2, 3, 0, 5], 7), "should be 11");
console.log(pairwise([], 100), "should be 0");
console.log(pairwise([1, 3, 2, 4], 4), "should be 1");
The keys of the map represent the other value needed to make a pair, and the values of the map are arrays of indices that have the value that would make a pair. The indices are inserted using unshift() so that pop() returns the first one that was inserted - the smallest one.
Iterating from the front guarantees that the smallest pairs are found first, and the map guarantees that any later index will know exactly what the earliest index that could make a pair is.
For a better performance you can save the arr.length into a variable, then for loop won't count every single loop.
function pairwise(arr, arg) {
let usedIndex = [];
let output = 0;
let length = arr.length;
for (let i = 0; i < length; i++) {
for (let j = i + 1; j < length; j++) {
if (
arr[i] + arr[j] == arg
&& usedIndex.indexOf(i) == -1
&& usedIndex.indexOf(j) == -1
) {
usedIndex.push(i, j)
output += i + j
}
}
}
return output;
}
Sort the list.
Have two counters walking from the ends. At each step check to see if the sum is what you want. If so, capture the desired metric.
Step 1 is O(n*logn).
Step 2 is O(n) -- each counter will go about halfway through the list, stopping when they meet.
Can someone please explain to me what I am doing wrong here...
This code is from eloquent javascript and it works fine
function sum(array) {
let total = 0;
for (let value of array) {
total += value;
}
return total;
}
And this is what I wrote for the exercise but returns NaN..
function sum(numArray) {
let add = 0;
for (let a = 0; a <= numArray.length; a++) {
let addIndex = numArray[a];
add += addIndex;
}
return add;
}
Your for loop goes out of array indexes. You have to use:
a < numArray.length
Instead of:
a <= numArray.length
You simply add undefined to add, because you run the index count to long.
for (let a = 0; a <= numArray.length; a++) {
// ^ wrong, takes last index + 1
function sum(numArray) {
let add = 0;
for (let a = 0; a < numArray.length; a++) {
let Addindex = numArray[a];
add += Addindex;
}
return add;
}
console.log(sum([1, 2, 3, 4]));
The issue is because of this a <= numArray.length. Change it to a < numArray.length. This case a[5] that is the 6th element or the element at 5th index is undefined as the array starts from 0 index. So it will add an undefined with previously added number and hence it will be NaN
function sum(numArray) {
let add = 0;
for (let a = 0; a < numArray.length; a++) {
let Addindex = numArray[a];
add += Addindex;
}
return add;
}
console.log(sum([1, 2, 3, 4, 5]))
You're getting an out-of-bounds error. In your for loop, you can change it to:
for (let a = 0; a < numArray.length; a++) {
OR
for (let a = 0; a <= numArray.length - 1; a++) {
The latter works too, but is harder to read.
You can also write a function that has two parameters, an array and a callback function that adds the values of the array like
function forEach(array, arrayAdder){
for (var i = 0; i < array.length; i ++)
arrayAdder(array[i]) ;
}
We can now initialize both the array and the sum like
var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], sum = 0;
After that we pass it into the function like this
forEach(array, function(number){
sum += number ;
});
Then print the answer
console.log(sum);