Iterate array and find the sum between a range of numbers - javascript

For example, If I pass the number 10 and the array [1, 2, 4, 4] the function should if the array was [4,2,1,1] the function should return false, because the sum was not between 2 numbers.

Use #some and #find functions to check if the sum of any two numbers in the given array equals the passed argument - see demo below:
function solution(num, array) {
return array.some(function(e, i) {
return (num - e + array.find(function(c, k) {
return c == e && i != k
})) == num;
});
}
console.log(solution(8, [-1, 2, 3, 4]), solution(8, [-1, 4, 3, 4]), solution(8, [4,3,45,2,5,3]));

The naive implementation for checking for a sum of two numbers is a nested loop, see below:
function isSumInArray(sum, array) {
for (let i=0; i < array.length; i++) {
for (let j=0; j < array.length; j++) {
if (array[i] + array[j] === sum && i !== j) {
return true
}
}
}
return false;
}
There are better ways to implement this, but I'm choosing it because I think it's the most simplistic to understand. You're going through the array twice here, and if the two numbers are equal to your desired sum (and they are not the same number in the array), then return true. If none of the combinations satisfy this condition, return false.

for any tow numbers in array
function test(array , n)
{
for(var i=0;i<array.length;i++)
{
for(var j=0;j<array.length ; j++)
if(array[i] + array[j] == n && i != j)
return true;
}
return false;
}
var array = [1,2,3,4,2];
console.log(test(array , 1));
console.log(test(array , 4));

I would solve it like this with no recursion, just looping over the elements and the next ones and exit the loop as soon as a solution is found:
function solution(n, arr) {
if (n < 0) return null;
if (n === 0) return [];
for (var i = 0; i < arr.length; i++) {
var first = arr[i]; // first addend
for (var j = i + 1; j < arr.length; j++) { // considering only next elements in the array
if (first + arr[j] === n) {
console.log(`found solution with ${first} and ${arr[j]}`);
return true;
}
}
}
console.log('no solution found');
return false;
}
console.log(solution(8, [4, 3, 45, 2, 5, 3]));
console.log(solution(8, [-1, 2, 3, 4]));

For each element, you need to "do the math" with every other element to see if they sum correctly.
The simplest implementation is a nested loop O(N^2).
Pseudocode:
def solution(list, target)
for each element e1 in list
for each element e2 in list
if e2 is e1
continue
end if
if e1 + e2 is target
return true
end if
loop
loop
return false
end def
Code:
function solution(list, target) {
for(let i = 0; i < list.length; i++) {
const e1 = list[i];
for(let j = 0; j < list.length; j++) {
const e2 = list[j];
if(i === j) { continue; }
if(e1 + e2 === target) {
return true;
}
}
}
return false;
}
console.log(solution([1,2,3,4,5], 2));
The next simplest solution is to realise that addition (ie. the sum operation) is commutative. This means that the order of the operands does not matter. 1+2 is the same as 2+1. This means that we need not re-calculate the sums for numbers we have already visited in the outer loop because as we advance we calculate the sum for a + b and by definition therefore cover b + a. The overall complexity remains the same though: O(N^2) (AFAICT).
Pseudocode:
def solution(list, target)
for each element e1 in list
for each element e2 that is to the right of e1 in list
if e1 + e2 is target
return true
end if
loop
loop
return false
end def
Code:
function solution(list, target) {
for(let i = 0; i < list.length; i++) {
const e1 = list[i];
for(let j = i+1; j < list.length; j++) {
const e2 = list[j];
if(e1 + e2 === target) {
return true;
}
}
}
return false;
}
console.log(solution([1,2,3,4,5], 5));
A better solution is to combine the two facts that addition is commutative and that we know what to look for without having to actually enumerate the list a second time. i.e. if a is the current element, then we know we want a + x = target so x can be easily calculated (it is the difference). By using an O(1) lookup data structure we can replace the inner loop and make the algorithm O(N) overall.
To re-state the problem, each element in the list must be summed with all the elements to the left and all those to the right. As we advance with the outer loop we perform the summing for all right-hand elements (because of the commutativity of addition). All elements to the right of an element will eventually be tested with it as the loop advances.
To sum with all the elements to the left we can replace the inner loop with a hash table indexed by the elements seen already. We can then use the fact that a + x = target, therefore, x = target - a to check for the presence of x in the hash table.
Pseudocode:
def solution(list, target)
var hash <- hashtable: [integer:boolean]
for each element in list
if hash has sum-element
return true
else
add element to hash
endif
loop
end def
Code:
function solution(list, target) {
const hash = new Set;
for(let e of list) {
if(hash.has(target-e)) {
return true;
}
hash.add(e);
}
return false;
}
solution([1,2,3,4,5], 3);

Related

How can I find all first indexes of sequence of consecutive zeroes in an array?

I am trying to push all first indexes that point to a start of a sequence of consecutive 0s from the array A into a new array arr.
var C determines the amount of 0s in the sequence. For example, if C is 2, the algorithm will look for 00s, if C is 3 it will look for 000s and so on. N is the length of an array A. The algorithm seems to work, but for some reason the values in the new array arr are duplicated
var A = [1, 0, 0, 1];
var N = 4;
var C = 1;
function S(A, N, C) {
var arr = [];
for (var i = 0; i < N; i++) {
for (var j = 0; j <= C; j++) {
if ((A[i] == 0) && (A[i + j] == 0)) {
arr.push(i);
}
}
}
console.log(arr);
return -1;
}
/// console result:
Array(5)
0: 1
1: 1
2: 2
3: 2
//Expected:
0: 1
1: 2
First I would like to recommend that you use more descriptive variable names. The fact that you need to describe what each of them means, means that they are not descriptive enough.
Also your variable N seems redundant, because arrays already have a .length property that you can use to see how many elements are in there.
The source of your error seems to be that you use a nested loop. There is no need to use nested loops. You only need to go through all elements once and keep track of the repeated zeroes. Every time you encounter a non-zero value, you reset the sequence count to 0. If do encounter a zero you increment the sequence count and afterwards you check if the sequence count is equal to the number of zeroes you passed as an argument. In that case you want to push the first index to the resulting array and reset the sequence count to 0 again.
function getFirstIndexesOfSequenceOfConsecutiveZeroes(input, numberOfRepeatedZeroes) {
if (numberOfRepeatedZeroes <= 0) {
throw new Error("numberOfRepeatedZeroes need to be 1 or higher");
}
var firstIndexes = [];
let sequenceStartIndex;
let sequenceCount = 0;
for (var i = 0; i < input.length; i++) {
if (input[i] !== 0) {
sequenceCount = 0;
} else {
if (sequenceCount == 0) {
sequenceStartIndex = i;
}
sequenceCount++;
}
if (sequenceCount === numberOfRepeatedZeroes) {
firstIndexes.push(sequenceStartIndex);
sequenceCount = 0;
}
}
return firstIndexes;
}
let input = [1, 0, 0, 1];
let numberOfRepeatedZeroes = 1;
console.log(getFirstIndexesOfSequenceOfConsecutiveZeroes(input, numberOfRepeatedZeroes));
Try:
function S(A, B, C) {
var arr = [];
for (var i = 0; i < B; i++) {
for (var j = 0; j <= C; j++) {
if ((A[i] == 0) && (A[i + j] == 0) && !arr.includes(i)) {
arr.push(i);
}
}
}
console.log(arr);
return -1;
}
With this simple add in the if, you check if the value is already in your array.

find all numbers disappeared in array

Please help me to solve this leetcode problem using javascript as I am a beginner and dont know why this code is not working
Ques: Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once.
Find all the elements of [1, n] inclusive that do not appear in this array.
var findDisappearedNumbers = function (nums) {
var numLength = nums.length;
nums.sort(function (a, b) { return a - b });
for (var i = 0; i < nums.length - 1; i++) {
if (nums[i + 1] === nums[i]) {
nums.splice(i, 1);
}
}
for (var k = 0; k < nums.length; k++) {
for (var j = 1; j <= numLength; j++) {
if (nums[k] !== j) {
return j;
}
}
}
};
if there is any error in my code please let me know;
i have done the following thing
first i have sorted the array in ascending order
then i have cut all the duplicate elements
then i have created loop that will check if nums[k] !== j ;
and it will return j which is the missing number;
for example this is the testcase [4,3,2,7,8,2,3,1]
first my code will sort this in ascending order [1,2,2,3,3,4,7,8]
then it will remove all duplicate elements and it will return [1,2,3,4,,7,8]
and then it will check nums[k] is not equal to j and it will print j
I think it'd be easier to create a Set of numbers from 1 to n, then just iterate through the array and delete every found item from the set:
var findDisappearedNumbers = function(nums) {
const set = new Set();
for (let i = 0; i < nums.length; i++) {
set.add(i + 1);
}
for (const num of nums) {
set.delete(num);
}
return [...set];
};
console.log(findDisappearedNumbers([4,3,2,7,8,2,3,1]));
To fix your existing code, I'm not sure what the logic you're trying to implement in the lower section, but you can iterate from 1 to numLength (in the outer loop, not the inner loop) and check to see if the given number is anywhere in the array. Also, since you're mutating the array with splice while iterating over it in the upper loop, make sure to subtract one from i at the same time so you don't skip an element.
var findDisappearedNumbers = function(nums) {
var numLength = nums.length;
nums.sort(function(a, b) {
return a - b
});
for (var i = 0; i < nums.length - 1; i++) {
if (nums[i + 1] === nums[i]) {
nums.splice(i, 1);
i--;
}
}
const notFound = [];
outer:
for (var j = 1; j < numLength; j++) {
for (var k = 0; k < nums.length; k++) {
if (nums[k] === j) {
continue outer;
}
}
notFound.push(j);
}
return notFound;
};
console.log(findDisappearedNumbers([4, 3, 2, 7, 8, 2, 3, 1]));
#CertainPerformance certainly cracked it again using the modern Set class. Here is a slighly more conservative approach using an old fashioned object:
console.log(missingIn([4,3,2,7,8,2,3,1]));
function missingIn(arr){
const o={};
arr.forEach((n,i)=>o[i+1]=1 );
arr.forEach((n) =>delete o[n] );
return Object.keys(o).map(v=>+v);
}
My solution for the problem to find the missing element
var findDisappearedNumbers = function(nums) {
const map={};
const result=[];
for(let a=0;a<nums.length;a++){
map[nums[a]]=a;
}
for(let b=0;b<nums.length;b++){
if(map[b+1]===undefined){
result.push(b+1)
}
}
return result;
};
Example 1:
Input: nums = [4,3,2,7,8,2,3,1]
Output: [5,6]
Example 2:
Input: nums = [1,1]
Output: [2]

Missing Number Algorithm Timeout Error (JavaScript)

I'm working on a Codewars Kata that is passing all tests, except it keeps timing out. Can anyone offer advice on how to optimize this? Thanks in advance!
Here is the question breakdown -
In this kata, we have an unsorted sequence of consecutive numbers from a to b, such that a < b always (remember a, is the minimum, and b the maximum value).
They were introduced an unknown amount of duplicates in this sequence and we know that there is an only missing value such that all the duplicate values and the missing value are between a and b, but never coincide with them.
Find the missing number with the duplicate numbers (duplicates should be output in a sorted array).
Let's see an example:
arr = [10,9,8,9,6,1,2,4,3,2,5,5,3]
find_dups_miss([10,9,8,9,6,1,2,4,3,2,5,5,3]) == [7,[2,3,5,9]]
And here is my solution -
function findDupsMiss(arr) {
let missingNum = [];
let newArr = [];
arr = arr.sort((a, b) => a - b);
let dup = [...new Set(arr)];
for (let y = 1; y < dup.length; y++) {
if (dup[y] - dup[y - 1] != 1) missingNum.push(dup[y] - 1)
}
for (let i = 0; i < arr.length; i++) {
for (let j = i + 1; j < arr.length; j++) {
if (arr[i] === arr[j]) newArr.push(arr[i])
}
}
missingNum.push(newArr);
return missingNum;
}
You could take the power of an object and the standard sorting of keys who could be used as indices of an array (positive 32 bit numbers).
This attempt has two parts
count all numbers
iterate all keys of the object with their appearances and
check if it has the missing number between the actual item and the previous item. If so, assign the missing values,
check the count and push the key if the count is greater than one.
This code completes in 7410 ms.
function findDupsMiss(arr) {
var hash = Object.create(null),
i = arr.length,
l,
v,
keys,
missing,
dupes = [],
previous, item;
while (i--) {
v = arr[i];
if (!hash[v]) {
hash[v] = 0;
}
hash[v]++;
}
keys = Object.keys(hash);
l = keys.length;
for (i = 0; i < l; i++) {
item = +keys[i];
if (previous + 1 !== item) {
missing = previous + 1;
}
if (hash[item] > 1) {
dupes.push(item);
}
previous = item;
}
return [missing, dupes];
}

leetcode 3sum assistance, how can i optimize this answer?

I have a solution that seems to pass most of the tests but is too slow. If i'm not mistaken, the complexity is O(n^3) due to the three for loops.
My idea was to start at the first three positions of the array at i, j and k, sum them, and see if it adds up to 0.
The functions objective is:
Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note:
The solution set must not contain duplicate triplets.
Example:
Given array nums = [-1, 0, 1, 2, -1, -4],
A solution set is:
[
[-1, 0, 1],
[-1, -1, 2]
]
var threeSum = function(nums) {
var originalArray = nums
var lengthArray = nums.length
//sort array smallest to largest
nums.sort(function(a,b) {
return a-b
})
function arrayEqual(array1, array2){
var equal = false
array1.forEach((value1) => {
if(array1 === array2){
equal = true
}
})
return equal
}
var sum = 0;
var answerArray = [];
//start from first digit and add from there
for(var i = 0; i<lengthArray; i++){
for(var j = i+1; j<lengthArray; j++){
for(var k = j+1; k<lengthArray; k++){
if((nums[i]+nums[j]+nums[k] === 0)){
if(!arrayEqual(answerArray, [nums[i],nums[j],nums[k]])){
answerArray.push([nums[i],nums[j],nums[k]])
}
}
}
}
}
return Array.from(new Set(answerArray.map(JSON.stringify)), JSON.parse)
};
How can i get around having to use three for loops to make this work (aka how do i optimize this solution?)
Think this problem in this way. Choose any number from the array say k. Now you need to find two other numbers in the array which add to -k. The resulting sum of three numbers will be k + (-k) = 0.
So this problem is reduced to find two numbers in the array which adds to a given number which is O(n) using two pointers method if given array is sorted.
In a nutshell, sort the array, take each number (k) one by one (O(n)), find two other numbers with sum -k (O(n)).
Total time complexity : O(n) * O(n) = O(n2)
You can solve the problem in a runtime of O(n^2). Here is the solution using JavaScript
var threeSum = function(nums) {
var solutions = [];
var target = 0;
nums.sort(function(a, b) {
return a - b;
});
for(var i = 0; i < nums.length - 2; i++) {
if(i === 0 || (i > 0 && nums[i] !== nums[i - 1])) {
var lo = i + 1;
var hi = nums.length - 1;
var sum = - nums[i];
while(lo < hi) {
if(nums[lo] + nums[hi] === sum) {
solutions.push([nums[i],nums[lo],nums[hi]]);
while (lo < hi && nums[lo] === nums[lo + 1]) lo++;
while (lo < hi && nums[hi] == nums[hi-1]) hi--;
lo++; hi--;
}else if (nums[lo] + nums[hi] > sum) {
hi--;
}else {
lo++;
}
}
}
};
return solutions;
}

Returning a missing element from a string of integers

I'm trying to write a function that accepts an array of unique integers between 0 and 9 (inclusive), and returns the missing element. Here's what I've got. So near but so far.
var currentPlace = 0;
function getMissingElement(superImportantArray){
while (currentPlace < 9){
for (var i = 0; i < 10; i++) {
var arrayNum = superImportantArray[currentPlace]
if (i == arrayNum) {
currentPlace ++;
console.log("so it's not " + i);
}
else if (i !=arrayNum) {
console.log("try..." + i);
}
}
}
}
// run
var myArray = [0,5,1,3,2,9,7,6,4]; // this test should return 8
getMissingElement(myArray);
I'm not sure i'm approaching this correctly. Thanks for your time.
Just wanted to post my answer from the comments. A simpler way to handle this, in my opinion, is to loop over the original array, and flag a new array at the index that they represent. For example, if the number is 4, flag the 4th index in the new array. The reason for all this is because once this is done, one index should be left unflagged. All that would be left to do is find the unflagged index.
Here's an example (I commented the code here, not the fiddle):
function findMissing(array, min, max) {
var missing, unfilledArray, i, j;
// Array to hold the flags
unfilledArray = [];
for (i = min, j = max; i <= j; i++) {
// Flag the index in the new array with the current value
unfilledArray[array[i]] = true;
}
for (i = min, j = max; i <= j; i++) {
// Loop over new array and find the unflagged index
currentUnfilled = unfilledArray[i];
if (!currentUnfilled) {
// Current index not flagged
missing = i;
break;
}
}
return missing;
}
DEMO: http://jsfiddle.net/6GAyw/
The other little feature I added was that you explicitly specify the minimum and maximum value, which, in your case, is 0 and 9. This feature allows this solution to be used on any range of numbers (unlike my original comment/suggestion).
And not that I fully understand big O notation, but I believe this is O(2n), not O(n^2), since there aren't nested loops/indexOf.
If you were looking to get all missing numbers in a range, you can easily modify the function to return an array of unflagged indexes instead. Here's an example:
function findMissing(array, min, max) {
var missing, unfilledArray, i, j;
// Array to hold the missing numbers
missing = [];
// Array to hold the flags
unfilledArray = [];
for (i = min, j = max; i <= j; i++) {
// Flag the index in the new array with the current value
unfilledArray[array[i]] = true;
}
for (i = min, j = max; i <= j; i++) {
// Loop over new array and find the unflagged index
currentUnfilled = unfilledArray[i];
if (!currentUnfilled) {
// Current index not flagged
missing.push(i);
}
}
return missing;
}
DEMO: http://jsfiddle.net/zFS89/
function getMissingElement(superImportantArray){
var result = [], length = Math.max(10, superImportantArray.length);
for (var i = 0; i < length; i++) {
if(superImportantArray.indexOf(i) == -1){
result.push(i);
}
}
return result;
}
Try this. This will return an array of missing elements else return an empty array.
DEMO FIDDLE
So here is one way to do it: Since you know that the array only contains values from 0 to 9, you can build a "set" of numbers and remove each "seen" value in the array from the set:
function getMissingElement(superImportantArray){
var numbers = {};
for (var i = 0; i < 10; i++) {
numbers[i] = true
}
for (var i = 0, l = superImportantArray.length; i < l; i++) {
delete numbers[superImportantArray[i]];
}
return Object.keys(numbers);
}
This would return an array of all numbers that are missing. If there can always only be one missing number you can easily modify this to directly return the number instead.
This should do it.
function getMissingElement(arrayTest) {
// create an array with all digits
var digitsArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var index;
for (var i=0; i<arrayTest.length; i++) {
// get the index of current digit on our array
index = digitsArray.indexOf(arrayTest[i]);
// if found, remove it from our array.
if (index >= 0) {
digitsArray.splice(index,1);
}
}
// the last remaining digit in the original array should be the one missing.
return (digitsArray[0]);
}
This one is better for the eyes.
function getMissingElement(superImportantArray) {
return superImportantArray.reduce(function (sum, value) {return sum - value;}, 45);
}

Categories