JavaScript start iterating Map() from specific element/index - javascript

I know that elements in a Map can be iterated over, in the order of insertion.
Let's assume we have this map:
const a = new Map();
a.set('x', 5);
a.set('y', 10);
a.set('z', 5);
And we want to find first element in a with the value 5 and then the next element with same value of 5.
// el will be 5, 10, 5...
for(const el of a) {
if(el === 0) {
// How can I iteratate over `a` starting from index(el) + 1
for (??) {}
}
}
If I was using an Array instead we could do something like (ignoring the keys):
const a = new Array(5, 10, 5);
for(let i = 0; i < a.length; ++i) {
if(a[i] === 5) {
// Here I can start iterating from i + 1
for(let j = i + 1; j < a.length; ++j) {
a[j] === 5 && console.log('FOUND!');
}
}
}
I am not very familiar with iterators, but I think it should be somehow possible to start iterating from a specific element in the map.
const x = a.get('x');
// iterate over Map `a` starting from the element that comes after x
One solution, that I am not particularly happy about, is to get a copy of the keys or entries each time we perform the operation const elements = a.entries(), so then we could quickly iterate over it, but it uses a lot of extra memory.

You could use a generators to do this,..
One advantage is that you can short circuit generators with a break..
Example below..
const a = new Map();
a.set('x', 5);
a.set('y', 10);
a.set('z', 5);
a.set('a', 10);
a.set('b', 5);
function* findFirstThenNext(m, v) {
let ix = 0;
for (const mm of m) {
if (v === mm[1]) {
yield {ix, key:mm[0]};
}
ix += 1;
}
}
let count = 0;
for (const ret of findFirstThenNext(a, 5)) {
console.log(`Found #${ret.ix} with key ${ret.key}`);
count ++;
if (count >= 2) break;
}
Using a mix of the for loop and iterators, you could create simple list, then do your double for loops using iterators.
The nice thing here, is if you use this sort of for looping in lots of places, then the makeOuterInnerIter function can be re-used for any iterable.
const a = new Map();
a.set('x', 5);
a.set('y', 10);
a.set('z', 5);
function* makeOuterInnerIter(iter) {
const stack = Array.from(iter);
for (let ol = 0; ol < stack.length; ol += 1) {
yield {
value: stack[ol],
inner: (function *inner() {
for (let il = ol + 1; il < stack.length; il += 1) yield stack[il];
})()
};
}
}
for (const {value: [okey, ovalue], inner} of makeOuterInnerIter(a)) {
console.log(`outer: ${okey}: ${ovalue}`);
for (const [ikey, ivalue] of inner) {
console.log(` inner: ${ikey}: ${ivalue}`);
}
}

Another approach with generators:
function* itWrapper(iterator, value) {
let found = false;
for(let item of iterator) {
if(item[1] == value) {
if(found) {
yield 'FOUND!'; // or: yield item[1];
} else {
found = true;
}
}
}
}
And then use like this:
for(let item of itWrapper(a[Symbol.iterator](), 5)) {
console.log(item);
}

Related

Merge sort visualisation using recursion and Promises

I've written a merge sort visualisation in p5.js which shows the steps of merge sort. This works fine as a sequential visualisation, but I'd quite like to show this as a true representation, where you can see each part of the array being sorted at the same time (with multiple sections being visualised sorting at the same time, to truly reflect the recursion). The code itself is relatively simple:
// Split the array recursively
let mid = Math.floor((right + left) / 2);
if (right - left < 1) {
return;
}
// My attempt to visualise this properly
await Promise.all([mergeSortSlice(array, left, mid), mergeSortSlice(array, mid + 1, right)]);
// THIS WORKS, but only for sequential sorting
// await mergeSortSlice(array, left, mid);
// await mergeSortSlice(array, mid + 1, right)
// Putting sleep(200) here also works, but doesn't show the steps of the sort as they are happening, just the result of each stage of the sort.
leftCounter = 0;
rightCounter = 0;
l = left;
r = mid + 1;
valuesStartIndex = l;
let leftArray = array.slice(left, r);
let rightArray = array.slice(r, right + 1);
while (rightCounter < rightArray.length && leftCounter < leftArray.length) {
if (leftArray[leftCounter] < rightArray[rightCounter]) {
array.splice(l + rightCounter, 1);
array.splice(valuesStartIndex, 0, leftArray[leftCounter]);
l++;
leftCounter++;
valuesStartIndex++;
await sleep(200);
} else {
array.splice(r, 1);
array.splice(valuesStartIndex, 0, rightArray[rightCounter]);
r++;
rightCounter++;
valuesStartIndex++;
await sleep(200);
}
}
The problem with using Promise.all is that the split parts of the array are getting mixed up, I believe due to the recursion? This is resulting in the array not getting sorted properly.
My timeout function:
async function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
The setup function and draw loop:
let values = [50, 10, 80, 56, 30, 25, 15]
function setup() {
createCanvas(600, 190);
frameRate(60);
mergeSort(values)
}
function draw() {
rectWidth = 10;
background(23);
stroke(0);
fill(255);
for (let i = 0; i < values.length; i++) {
rect(i * rectWidth, height - values[i], rectWidth, values[i]);
}
}
The combination of async functions and recursion makes it difficult for me to come up with a solution for this. Any help/advice would be much appreciated.
You were actually very close to having a working solution. Your issue is that you are creating a bunch of global variables inside your mergeSortSlice function:
// These were all missing the let keyword
// And were therefore either assigning or implicitly declaring
// globally scoped variables.
let leftCounter = 0;
let rightCounter = 0;
let l = left;
let r = mid + 1;
let valuesStartIndex = l;
let leftArray = array.slice(left, r);
let rightArray = array.slice(r, right + 1);
When two instances of a function invocation being run as part of a Promise each of which await on timeouts, their execution is going to be interleaved (which you want so you can graphically represent the theoretical parallelism). However, when those functions alter global variables this is a classic shared memory multi-threading bug.
Here's an adaptation of your code with the bug fixed, highlighting added, and a slightly different delay strategy:
function merge_sort(p) {
const Mode = {
Shuffling: 0,
Sorting: 1
};
const spacing = 5;
let array = [...Array(40)].map((_, i) => i);
let highlights = [];
let itemWidth;
let itemHeight;
let currentMode = Mode.Shuffling;
let iterator;
let frameRate = 8;
let redrawPromise;
let signalRedraw;
p.setup = function() {
p.createCanvas(p.windowWidth, p.windowHeight);
p.frameRate(frameRate * 5);
itemWidth = (p.width - (spacing * (array.length + 1))) / array.length;
itemHeight = p.height - spacing * 2;
iterator = shuffle();
initRedrawPromise();
};
function initRedrawPromise() {
redrawPromise =
new Promise(resolve => {
signalRedraw = resolve;
});
redrawPromise.then(() => initRedrawPromise());
}
p.draw = function() {
p.background('white');
// draw
for (let i = 0; i < array.length; i++) {
if (highlights[i]) {
p.fill(highlights[i]);
} else {
p.fill('blue');
}
let fractionalHeight = (array[i] + 1) / array.length;
let pixelHeight = fractionalHeight * itemHeight;
p.rect(
(i + 1) * spacing + i * itemWidth,
spacing + (itemHeight - pixelHeight),
itemWidth,
pixelHeight
);
}
signalRedraw();
if (currentMode === Mode.Shuffling) {
// update
let next = iterator.next();
if (next.value) {
// Done suffle, switch to sort
currentMode = Mode.Sorting;
p.frameRate(frameRate);
sort().then(() => {
// switch back to shuffling
currentMode = Mode.Shuffling;
p.frameRate(frameRate * 5);
iterator = shuffle();
});
}
}
};
p.keyPressed = function(e) {
if (e.key === 'ArrowRight' || e.key === 'ArrowUp') {
frameRate++;
p.frameRate(frameRate);
} else if (e.key === 'ArrowLeft' || e.key === 'ArrowDown') {
frameRate = Math.max(0, frameRate - 1);
p.frameRate(frameRate);
}
}
// shuffle the array. yield false for each step where the array is not yet shuffled. yield true once the array is shuffled.
function* shuffle() {
// for each position in the array (except the last position),
// if the chosen item is not the current item, swap the two items.
for (let i = 0; i < array.length - 1; i++) {
highlight(i);
yield false;
let j = randomInt(i, array.length);
if (j !== i) {
highlight(i, j);
yield false;
swap(i, j);
highlight(j, i);
yield false;
} else {
highlight(i);
yield false;
}
}
yield true;
}
function sort() {
highlights = [];
return sortSlice(0, array.length - 1);
}
async function sortSlice(left, right) {
if (right - left < 1) {
return;
}
// Split the array recursively
let mid = Math.floor((right + left) / 2);
await Promise.all([sortSlice(left, mid), sortSlice(mid + 1, right)]);
for (let ix = left; ix <= right; ix++) {
highlights[ix] = undefined;
}
let leftCounter = 0;
let rightCounter = 0;
let l = left;
let r = mid + 1;
let valuesStartIndex = l;
let leftArray = array.slice(left, r);
let rightArray = array.slice(r, right + 1);
while (rightCounter < rightArray.length && leftCounter < leftArray.length) {
if (leftArray[leftCounter] < rightArray[rightCounter]) {
array.splice(l + rightCounter, 1);
array.splice(valuesStartIndex, 0, leftArray[leftCounter]);
highlights[valuesStartIndex] = 'green';
highlights[r] = 'red';
l++;
leftCounter++;
valuesStartIndex++;
} else {
array.splice(r, 1);
array.splice(valuesStartIndex, 0, rightArray[rightCounter]);
highlights[valuesStartIndex] = 'green';
r++;
rightCounter++;
valuesStartIndex++;
highlights[l + rightCounter] = 'red';
}
// at each merge step wait for a redraw that shows this step
await redrawPromise;
highlights[valuesStartIndex - 1] = 'gray';
for (let ix = valuesStartIndex; ix <= right; ix++) {
highlights[ix] = undefined;
}
}
}
function swap(i, j) {
const tmp = array[i];
array[i] = array[j];
array[j] = tmp;
}
function randomInt(lowerBound, upperBound) {
return lowerBound + Math.floor(Math.random() * (upperBound - lowerBound));
}
function highlight(i, j) {
highlights = [];
if (i !== undefined) {
highlights[i] = 'green';
}
if (j !== undefined) {
highlights[j] = 'red';
}
}
}
sketch = new p5(merge_sort);
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>

How to return the first occurrence of repeated item in an array using for loop?

I am trying to build logic currently with arrays and data structure. I am trying to implement the logic using for loop
function getRepeatingNumber(arr) {
for (var i = 0; i < arr.length; i++) {
for (var j = i + 1; j < arr.length; j++) {
if (arr[i] === arr[j]) {
return arr[i];
}
}
}
return undefined;
}
getRepeatingNumber([2, 3, 6, 5, 2]);
the above function takes in array and returns a repeated item in the array so in the above case it will return 2. But what if I have an array something like this arr[2,3,3,6,5,2] in this case it should return 3 but as the outer loop has index [0] which is 2 as the reference it will return 2 as the answer.
How to implement a function that returns the first occurrence of the repeated item.
Instead of iterating with j in the part after i, iterate the part before i:
function getRepeatingNumber(arr){
for (var i = 1; i < arr.length; i++) {
for (var j = 0; j < i; j++) {
if (arr[i] === arr[j]) {
return arr[i];
}
}
}
}
console.log(getRepeatingNumber([2,3,3,6,5,2]));
Note that an explicit return undefined is not needed, that is the default behaviour already.
You could also use indexOf to shorten the code a bit:
function getRepeatingNumber(arr){
for (var i = 1; i < arr.length; i++) {
if (arr.indexOf(arr[i]) < i) {
return arr[i];
}
}
}
console.log(getRepeatingNumber([2,3,3,6,5,2]));
You could even decide to make use of find -- which will return undefined in case of no match (i.e. no duplicates in our case):
function getRepeatingNumber(arr){
return arr.find((a, i) => {
if (arr.indexOf(a) < i) {
return true;
}
});
}
console.log(getRepeatingNumber([2,3,3,6,5,2]));
If you do this for huge arrays, then it would become important to have a solution that runs with linear time complexity. In that case, a Set will be useful:
function getRepeatingNumber(arr){
var set = new Set;
return arr.find(a => {
if (set.has(a)) return true;
set.add(a);
});
}
console.log(getRepeatingNumber([2,3,3,6,5,2]));
And if you are into functions of functions, and one-liners, then:
const getRepeatingNumber = r=>(t=>r.find(a=>[t.has(a),t.add(a)][0]))(new Set);
console.log(getRepeatingNumber([2,3,3,6,5,2]));
You need a data structure to keep track of first occurring index.
My recommendation is to use an array to store all the index of repeating numbers. Sort the array in ascending order and return the item at first index from the array.
function getRepeatingNumber(arr){
var resultIndexArr = [];
var count = 0;
var flag = 0;
for(var i=0;i<arr.length;i++)
{
for(var j=i+1;j<arr.length;j++)
{
if(arr[i] === arr[j])
{
flag = 1;
resultIndexArr[count++] = j;
}
}
}
resultIndexArr.sort((a, b) => a - b);
var resultIndex = resultIndexArr[0];
if(flag === 1)
return arr[resultIndex];
else
return;
}
console.log(getRepeatingNumber([2,3,6,5,2])); // test case 1
console.log(getRepeatingNumber([2,3,3,6,5,2])); // test case 2
console.log(getRepeatingNumber([2,5,3,6,5,2])); // test case 3
This will return correct result, but this is not the best solution. The best solution is to store your items in an array, check for each iteration if the item already exists in your array, if it exists then just return that item.
as a javascript dev you should be comfortable wit functional programming & higher-order functions so check the doc to get more understanding of some useful functions: like filter - find - reduce - findIndex map ...
Documentation
Now to answer your question:
at first you should think by step :
Get the occurrence of an item in an array as function:
const arr = [2, 5, 6, 2, 4, 5, 6, 8, 2, 5, 2]
const res = arr.reduce((numberofOcc, item) => {
if (item === 2)
numberofOcc++
return numberofOcc
}, 0);
console.log(`result without function ${res}`);
/* so my function will be */
const occurenceFun = (num, arr) => {
return arr.reduce((numberofOcc, item) => {
if (item === num)
numberofOcc++
return numberofOcc
}, 0);
}
console.log(`result using my function ${occurenceFun(2, arr)}`);
Now i have this function so i can use it inside another function to get the higher occurrence i have in an array
const arr = [1, 2, 5, 6, 8, 7, 2, 2, 2, 10, 10, 2]
const occurenceFun = (num, arr) => {
return arr.reduce((numberofOcc, item) => {
if (item === num)
numberofOcc++
return numberofOcc
}, 0);
}
/*let's create our function*/
const maxOccurenceFun = arr => {
let max = 0;
arr.forEach(el => {
if (max < occurenceFun(el, arr)) {
max = el
}
})
return max;
}
console.log(`the max occurence in this array is : ${maxOccurenceFun(arr)}`);

How to use array.push inside a function

I'm trying to return the array an array of numbers that conform to the two if statements. The prompt came from leet code, "Self Dividing Numbers", and asks to take in two arguments, a lower and upper bound and check if whether or not each number in that range is divisible by the digits of each individual number.
When I console.log(num) (the commented out portion, I get a correct list of numbers, but not in an array format. To fix this I thought to add a variable, result and return result after pushing an array to result inside the for loop. However when I do this, i only get the first correct term in an array, but not the full array.
How can this be fixed? I've tried moving the return statement in various locations, but that did not fix the issue.
The function should return [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 15, 22];
function selfDividingNumbers(left, right) {
for (let j = left; j <= right; j++) {
let num = j;
let result = []
let strNum = num.toString();
let dividingDigit = 0;
for (let i = 0; i < strNum.length; i++) {
if (num % parseInt(strNum[i]) == 0) {
dividingDigit++;
}
if (dividingDigit == strNum.length) {
result.push(num)
//console.log(num)
}
}
return result
}
};
console.log(selfDividingNumbers(1, 22));
From your expected output, define result at the very top of the function, and then return only after completely iterating through both loops:
function selfDividingNumbers(left, right) {
let result = []
for (let j = left; j <= right; j++) {
let num = j;
let strNum = num.toString();
let dividingDigit = 0;
for (let i = 0; i < strNum.length; i++) {
if (num % parseInt(strNum[i]) == 0) {
dividingDigit++;
}
if (dividingDigit == strNum.length) {
result.push(num)
//console.log(num)
}
}
}
return result
};
console.log(selfDividingNumbers(1, 22));
To be more concise, you might use .filter check whether .every digit divides evenly:
function selfDividingNumbers(left, right) {
return Array.from(
{ length: right - left },
(_, i) => i + left
)
.filter((num) => {
const digits = String(num).split('');
if (digits.includes(0)) {
return false;
}
return digits.every(digit => num % digit === 0);
});
}
console.log(selfDividingNumbers(1, 22));
When you declare let result = [] inside your for loop you are telling your code to recreate this array every time your loop iterates, thus, removing all previous results pushed into it. Instead, you need to move this outside your for loop to stop this from happening.
Lastly, you need to return only after you're outer for loop is complete, as returning inside your for loop will stop the function from running (and thus stop the loop).
See working example below:
function selfDividingNumbers(left, right) {
let result = [];
for (let j = left; j <= right; j++) {
let num = j;
let strNum = num.toString();
let dividingDigit = 0;
for (let i = 0; i < strNum.length; i++) {
if (num % parseInt(strNum[i]) == 0) {
dividingDigit++;
}
if (dividingDigit == strNum.length) {
result.push(num)
}
}
}
return result
};
console.log(selfDividingNumbers(1, 22));

How to convert this combination sum algorithm from java to javascript

Here is the leetcode question, for combination sum problem.
One answer code is here in java. (or see follow)
public class Solution {
public List<List<Integer>> combinationSum(int[] cands, int t) {
Arrays.sort(cands); // sort candidates to try them in asc order
List<List<List<Integer>>> dp = new ArrayList<>();
for (int i = 1; i <= t; i++) { // run through all targets from 1 to t
List<List<Integer>> newList = new ArrayList(); // combs for curr i
// run through all candidates <= i
for (int j = 0; j < cands.length && cands[j] <= i; j++) {
// special case when curr target is equal to curr candidate
if (i == cands[j]) newList.add(Arrays.asList(cands[j]));
// if current candidate is less than the target use prev results
else for (List<Integer> l : dp.get(i-cands[j]-1)) {
if (cands[j] <= l.get(0)) {
List cl = new ArrayList<>();
cl.add(cands[j]); cl.addAll(l);
newList.add(cl);
}
}
}
dp.add(newList);
}
return dp.get(t-1);
}
}
I need to convert it in javascript.
Here is my attempt.
function sortFunc(a, b) {
return a-b;
}
function combinationSum(cands, t) {
cands.sort(sortFunc);
let dp = []; //[[[]]];
for (let i = 1; i <= t; i++) {
console.log('-- i --');
console.log(i);
let newList = []; // [[]];
for (let j = 0; j < cands.length && cands[j] <= i; j++)
{
console.log('-- j --');
console.log(j);
if (i === cands[j]) {
console.log('-- push --');
console.log(i);
newList.push([cands[j]]);
}
else {
// list of int
let myListList = dp[i-cands[j]-1];
for(let k=0; k<myListList.length; k++) {
let myList = myListList;
if(cands[j] <= myList[0]) {
myListList.unshift([cands[j]]);
newList.push(myListList);
}
}
}
}
dp.push(newList);
}
return dp[t-1];
}
let arr = [2, 3, 5];
let t = 15;
let out = combinationSum(arr, t);
console.log(out);
I have some understanding of the code, but not a lot. Currently, my javascript is in infinite loop.
Does anyone know why?
Or if you have a better solution for "combination sum"?
You went off the rails a bit in the last for loop and kept adding to myNewList inside the loop based on it's length so the loop never ended.
Here's a version that sticks pretty close to the original:
function sortFunc(a, b) {
return a - b;
}
function combinationSum(cands, t) {
cands.sort(sortFunc);
let dp = []; //[[[]]];
for (let i = 1; i <= t; i++) {
let newList = []; // [[]];
for (let j = 0; j < cands.length && cands[j] <= i; j++) {
if (i === cands[j]) {
newList.push([cands[j]]);
} else {
for (l of dp[i - cands[j] - 1]) { // for of is similar to `for (List<Integer> l : dp.get(i-cands[j]-1))`
if (cands[j] <= l[0]) {
let cl = [cands[j], ...l] // use spread ...l to get ArrayList.addall() behavior
newList.push(cl)
}
}
}
}
dp.push(newList);
}
return dp[t - 1];
}
let arr = [2, 3, 5, 4];
let t = 7;
let out = combinationSum(arr, t);
console.log(out);
The problem is this line:
let myList = myListList;
You create a reference to myListList rather than a copy so that when you start manipulating the myListList array you end up in an endless loop.
to fix it, copy the myListList array like this
let myList = myListList.splice();

Pair of elements from a specified array whose sum equals a specific target number

I am in mid of my JavaScript session. Find this code in my coding exercise. I understand the logic but I didn't get this map[nums[x]] condition.
function twoSum(nums, target_num) {
var map = [];
var indexnum = [];
for (var x = 0; x < nums.length; x++)
{
if (map[nums[x]] != null)
// what they meant by map[nums[x]]
{
index = map[nums[x]];
indexnum[0] = index+1;
indexnum[1] = x+1;
break;
}
else
{
map[target_num - nums[x]] = x;
}
}
return indexnum;
}
console.log(twoSum([10,20,10,40,50,60,70],50));
I am trying to get the Pair of elements from a specified array whose sum equals a specific target number. I have written below code.
function arraypair(array,sum){
for (i = 0;i < array.length;i++) {
var first = array[i];
for (j = i + 1;j < array.length;j++) {
var second = array[j];
if ((first + second) == sum) {
alert('First: ' + first + ' Second ' + second + ' SUM ' + sum);
console.log('First: ' + first + ' Second ' + second);
}
}
}
}
var a = [2, 4, 3, 5, 6, -2, 4, 7, 8, 9];
arraypair(a,7);
Is there any optimized way than above two solutions? Can some one explain the first solution what exactly map[nums[x]] this condition points to?
Using HashMap approach using time complexity approx O(n),below is the following code:
let twoSum = (array, sum) => {
let hashMap = {},
results = []
for (let i = 0; i < array.length; i++){
if (hashMap[array[i]]){
results.push([hashMap[array[i]], array[i]])
}else{
hashMap[sum - array[i]] = array[i];
}
}
return results;
}
console.log(twoSum([10,20,10,40,50,60,70,30],50));
result:
{[10, 40],[20, 30]}
I think the code is self explanatory ,even if you want help to understand it,let me know.I will be happy enough to for its explanation.
Hope it helps..
that map value you're seeing is a lookup table and that twoSum method has implemented what's called Dynamic Programming
In Dynamic Programming, you store values of your computations which you can re-use later on to find the solution.
Lets investigate how it works to better understand it:
twoSum([10,20,40,50,60,70], 50)
//I removed one of the duplicate 10s to make the example simpler
In iteration 0:
value is 10. Our target number is 50. When I see the number 10 in index 0, I make a note that if I ever find a 40 (50 - 10 = 40) in this list, then I can find its pair in index 0.
So in our map, 40 points to 0.
In iteration 2:
value is 40. I look at map my map to see I previously found a pair for 40.
map[nums[x]] (which is the same as map[40]) will return 0.
That means I have a pair for 40 at index 0.
0 and 2 make a pair.
Does that make any sense now?
Unlike in your solution where you have 2 nested loops, you can store previously computed values. This will save you processing time, but waste more space in the memory (because the lookup table will be needing the memory)
Also since you're writing this in javascript, your map can be an object instead of an array. It'll also make debugging a lot easier ;)
function twoSum(arr, S) {
const sum = [];
for(let i = 0; i< arr.length; i++) {
for(let j = i+1; j < arr.length; j++) {
if(S == arr[i] + arr[j]) sum.push([arr[i],arr[j]])
}
}
return sum
}
Brute Force not best way to solve but it works.
Please try the below code. It will give you all the unique pairs whose sum will be equal to the targetSum. It performs the binary search so will be better in performance. The time complexity of this solution is O(NLogN)
((arr,targetSum) => {
if ((arr && arr.length === 0) || targetSum === undefined) {
return false;
} else {
for (let x = 0; x <=arr.length -1; x++) {
let partnerInPair = targetSum - arr[x];
let start = x+1;
let end = (arr.length) - 2;
while(start <= end) {
let mid = parseInt(((start + end)/2));
if (arr[mid] === partnerInPair) {
console.log(`Pairs are ${arr[x]} and ${arr[mid]} `);
break;
} else if(partnerInPair < arr[mid]) {
end = mid - 1;
} else if(partnerInPair > arr[mid]) {
start = mid + 1;
}
}
};
};
})([0,1,2,3,4,5,6,7,8,9], 10)
function twoSum(arr, target) {
let res = [];
let indexes = [];
for (let i = 0; i < arr.length - 1; i++) {
for (let j = i + 1; j < arr.length; j++) {
if (target === arr[i] + arr[j] && !indexes.includes(i) && !indexes.includes(j)) {
res.push([arr[i], arr[j]]);
indexes.push(i);
indexes.push(j);
}
}
}
return res;
}
console.log('Result - ',
twoSum([1,2,3,4,5,6,6,6,6,6,6,6,6,6,7,8,9,10], 12)
);
Brute force.
const findTwoNum = ((arr, value) => {
let result = [];
for(let i= 0; i< arr.length-1; i++) {
if(arr[i] > value) {
continue;
}
if(arr.includes(value-arr[i])) {
result.push(arr[i]);
result.push(value-arr[i]);
break;;
}
}
return result;
});
let arr = [20,10,40,50,60,70,30];
const value = 120;
console.log(findTwoNum(arr, value));
OUTPUT : Array [50, 70]
function twoSum(arr){
let constant = 17;
for(let i=0;i<arr.length-2;i++){
for(let j=i+1;j<arr.length;j++){
if(arr[i]+arr[j] === constant){
console.log(arr[i],arr[j]);
}
}
}
}
let myArr = [2, 4, 3, 5, 7, 8, 9];
function getPair(arr, targetNum) {
for (let i = 0; i < arr.length; i++) {
let cNum = arr[i]; //my current number
for (let j = i; j < arr.length; j++) {
if (cNum !== arr[j] && cNum + arr[j] === targetNum) {
let pair = {};
pair.key1 = cNum;
pair.key2 = arr[j];
console.log(pair);
}
}
}
}
getPair(myArr, 7)
let sumArray = (arr,target) => {
let ar = []
arr.forEach((element,index) => {
console.log(index);
arr.forEach((element2, index2) => {
if( (index2 > index) && (element + element2 == target)){
ar.push({element, element2})
}
});
});
return ar
}
console.log(sumArray([8, 7, 2, 5, 3, 1],10))
Use {} hash object for storing and fast lookups.
Use simple for loop so you can return as soon as you find the right combo; array methods like .forEach() have to finish iterating no matter what.
And make sure you handle edges cases like this: twoSum([1,2,3,4], 8)---that should return undefined, but if you don't check for !== i (see below), you would erroneously return [4,4]. Think about why that is...
function twoSum(nums, target) {
const lookup = {};
for (let i = 0; i < nums.length; i++) {
const n = nums[i];
if (lookup[n] === undefined) {//lookup n; seen it before?
lookup[n] = i; //no, so add to dictionary with index as value
}
//seen target - n before? if so, is it different than n?
if (lookup[target - n] !== undefined && lookup[target - n] !== i) {
return [target - n, n];//yep, so we return our answer!
}
}
return undefined;//didn't find anything, so return undefined
}
We can fix this with simple JS object as well.
const twoSum = (arr, num) => {
let obj = {};
let res = [];
arr.map(item => {
let com = num - item;
if (obj[com]) {
res.push([obj[com], item]);
} else {
obj[item] = item;
}
});
return res;
};
console.log(twoSum([2, 3, 2, 5, 4, 9, 6, 8, 8, 7], 10));
// Output: [ [ 4, 6 ], [ 2, 8 ], [ 2, 8 ], [ 3, 7 ] ]
Solution In Java
Solution 1
public static int[] twoNumberSum(int[] array, int targetSum) {
for(int i=0;i<array.length;i++){
int first=array[i];
for(int j=i+1;j<array.length;j++){
int second=array[j];
if(first+second==targetSum){
return new int[]{first,second};
}
}
}
return new int[0];
}
Solution 2
public static int[] twoNumberSum(int[] array, int targetSum) {
Set<Integer> nums=new HashSet<Integer>();
for(int num:array){
int pmatch=targetSum-num;
if(nums.contains(pmatch)){
return new int[]{pmatch,num};
}else{
nums.add(num);
}
}
return new int[0];
}
Solution 3
public static int[] twoNumberSum(int[] array, int targetSum) {
Arrays.sort(array);
int left=0;
int right=array.length-1;
while(left<right){
int currentSum=array[left]+array[right];
if(currentSum==targetSum){
return new int[]{array[left],array[right]};
}else if(currentSum<targetSum){
left++;
}else if(currentSum>targetSum){
right--;
}
}
return new int[0];
}
function findPairOfNumbers(arr, targetSum) {
var low = 0, high = arr.length - 1, sum, result = [];
while(low < high) {
sum = arr[low] + arr[high];
if(sum < targetSum)
low++;
else if(sum > targetSum)
high--;
else if(sum === targetSum) {
result.push({val1: arr[low], val2: arr[high]});
high--;
}
}
return (result || false);
}
var pairs = findPairOfNumbers([1,2,3,4,4,5], 8);
if(pairs.length) {
console.log(pairs);
} else {
console.log("No pair of numbers found that sums to " + 8);
}
Simple Solution would be in javascript is:
var arr = [7,5,10,-5,9,14,45,77,5,3];
var arrLen = arr.length;
var sum = 15;
function findSumOfArrayInGiven (arr, arrLen, sum){
var left = 0;
var right = arrLen - 1;
// Sort Array in Ascending Order
arr = arr.sort(function(a, b) {
return a - b;
})
// Iterate Over
while(left < right){
if(arr[left] + arr[right] === sum){
return {
res : true,
matchNum: arr[left] + ' + ' + arr[right]
};
}else if(arr[left] + arr[right] < sum){
left++;
}else{
right--;
}
}
return 0;
}
var resp = findSumOfArrayInGiven (arr, arrLen, sum);
// Display Desired output
if(resp.res === true){
console.log('Matching Numbers are: ' + resp.matchNum +' = '+ sum);
}else{
console.log('There are no matching numbers of given sum');
}
Runtime test JSBin: https://jsbin.com/vuhitudebi/edit?js,console
Runtime test JSFiddle: https://jsfiddle.net/arbaazshaikh919/de0amjxt/4/
function sumOfTwo(array, sumNumber) {
for (i of array) {
for (j of array) {
if (i + j === sumNumber) {
console.log([i, j])
}
}
}
}
sumOfTwo([1, 2, 3], 4)
function twoSum(args , total) {
let obj = [];
let a = args.length;
for(let i = 0 ; i < a ; i++){
for(let j = 0; j < a ; j++){
if(args[i] + args[j] == total) {
obj.push([args[i] , args[j]])
}
}
}
console.log(obj)}
twoSum([10,20,10,40,50,60,70,30],60);
/* */

Categories

Resources