How to convert this combination sum algorithm from java to javascript - 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();

Related

Javascript twoSum algorithm: Given an array of integers, return indices of the two numbers such that they add up to a specific target

Given an array of integers, return indices of the two numbers such that they add up to a specific target.
Example:
Given nums = [3, 2, 4], target = 6,
Because nums[1] + nums[2] = 2 + 4 = 6
return [1, 2].
Solution
var twoSum = function(nums, target) {
for(let i = 0; i <= nums.length; i++){
for(let j = 0; j <= nums.length; j++){
if(nums[i] + nums[j] == target){
return [i, j]
}
}
}
};
The code above works in other cases but not this one.
Expected result [1,2]
Output [0,0]
For instance, I've tried to use a different array of numbers and a different target and it works even if you change the order of the numbers
Example:
New array: [15, 7, 11, 2], target = 9,
Output: [1, 3].
I don't understand what is wrong with the solution and I hope that someone can explain. Thanks
You can use a very simple technique.
Basically, you can check if the difference of target & the element in the current iteration, exists in the array.
Assuming same index cannot be used twice
nums = [3, 2, 4], target = 6
nums[0] = 3
target = 6
diff = 6 - 3 = 3
nums.indexOf[3] = 0 // FAILURE case because it's the same index
// move to next iteration
nums[1] = 2
target = 6
diff = 6 - 2 = 4
nums.indexOf(4) = 2 // SUCCESS '4' exists in the array nums
// break the loop
Here's the accepted answer by the leetcode.
/**
* #param {number[]} nums
* #param {number} target
* #return {number[]}
*/
var twoSum = function(nums, target) {
for (let index = 0; index < nums.length; index++) {
const diff = target - nums[index];
const diffIndex = nums.indexOf(diff);
// "diffIndex !== index" takes care of same index not being reused
if (diffIndex !== -1 && diffIndex !== index) {
return [index, diffIndex];
}
}
};
Runtime: 72 ms, faster than 93.74% of JavaScript online submissions for Two Sum.
Memory Usage: 38.5 MB, less than 90.55% of JavaScript online submissions for Two Sum.
Can anybody help me in reducing the memory usage also?
I don't understand what is wrong with the solution and I hope that
someone can explain ?
Here you're both inner and outer loop start from 0th so in the case [3,2,4] and target 6 it will return [0,0] as 3 + 3 is equal to target, so to take care of same index element not being used twice created a difference of 1 between outer and inner loop
Make outer loop to start from 0th index and inner loop with value i+1
var twoSum = function(nums, 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([15, 7, 11, 2],9))
console.log(twoSum([3, 2, 4],6))
we can solve this problem in O(n) by using the map/object.
We can maintain a map or object which will save all values with index and then we can iterate the array and find target-nums[i] for each value and will find that value in map/object.
let's see this by example:-
nums=[2,7,11,15]
target = 9;
then map/object will be
mm={
2 : 0,
7: 1,
11: 2,
15: 3
}
then for each value, we will find diff and find that diff in map/object.
for i=0 diff= 9-2=7 and mm.has(7) is true so our answer is 2 and 7.
for their index we can use mm.get(7) and i.
return [mm.get(7), i]
var twoSum = function(nums, target) {
let mm=new Map();
for(let i=0;i<nums.length;i++){
mm.set(nums[i],i);
}
let diff=0;
let j;
for(let i=0;i<nums.length;i++){
diff=target-nums[i];
if(mm.has(diff) && i!=mm.get(diff)){
j=mm.get(diff);
if(j>i){
return [i,j];
}else{
return [j,i];
}
}
}
};
Runtime: 76 ms, faster than 88.18% of JavaScript online submissions for Two Sum.
Memory Usage: 41.4 MB, less than 13.32% of JavaScript online submissions for Two Sum.
Your solution works as expected. For nums = [3, 2 ,4] and target = 6, [0, 0] is a valid solution for the outlined problem as nums[0] + nums[0] = 3 + 3 = 6.
If you need two different indices (In my understanding this is not required by the task) you can add an additional check for inequality (nums[i] + nums[j] == target && i != j).
var twoSum = function(nums, target) {
for(let i=0; i<nums.length; i++){
for(let j=i+1; j<nums.length; j++){
if(nums[j] === target - nums[i]){
return [i, j];
}
}
}
};
Here's a simple method to solve this problem and its efficient using different type of inputs using JavaScript.
Like with input of ([3,3], 6) and its expected output will be [0,1] and input like ([3,2,4], 6) with expected output will be [2,4]
var twoSum = function (nums, target) {
for (let i = 0; i <= nums.length; i++) {
for (let j = 0; j <= nums.length; j++) {
if (i !== j) {
if (nums[i] + nums[j] === target) {
return [i, j];
}
}
}
}
};
console.log(twoSum([3, 2, 4], 6));
var twoSum = function (nums, target) {
var len = nums.length;
for (var i = 0; i < len; i++) {
for (var j = i + 1; j < len; j++) {
if (nums[i] + nums[j] == target) {
return [i,j];
}
}
}
};
var twoSum = function(nums, target) {
for(var i=0;i<nums.length;i++){
for(var j=i+1;j<nums.length;j++){
temp = nums[i]+nums[j];
if(temp == target){
return [i,j]
}
}
}
};
console.log(twoSum([15, 7, 11, 2],9))
console.log(twoSum([3, 2, 4],6))
console.log(twoSum([3,3],6))
This works perfectly and the Runtime: 72 ms lesser than 84ms
Another efficient solution way to solve this problem with an O(n) time complexity is not using nested loops. I commented the steps, so JS developers can easy understand. Here is my solution using golang:
func twoSum(intArray []int, target int) []int {
response := []int{-1, -1} // create an array as default response
if len(intArray) == 0 { // return default response if the input array is empty
return response
}
listMap := map[int]int{} // create a Map, JS => listMap = new Map()
for index, value := range intArray { // for loop to fill the map
listMap[value] = index
}
for i, value := range intArray { // for loop to verify if the subtraction is in the map
result := target - value
if j, ok := listMap[result]; ok && i != j { // this verify if a property exists on a map in golang. In the same line we verify it i == j.
response[0] = i
response[1] = j
return response
}
}
return response
}
var twoSum = function(nums, target) {
var numlen = nums.length;
for(let i=0; i<=numlen; i++){
for(let j=i+1;j<numlen;j++){
var num1 = parseInt(nums[i]);
var num2 = parseInt(nums[j]);
var num3 = num1 + num2;
if(num3 == target){
return[i,j]
}
}
}
};
I suppose this could be a better solution. Instead of nesting loops, this provides a linear solution.
(PS: indexOf is kinda a loop too with O(n) complexity)
var twoSum = function (nums, target) {
const hm = {}
nums.forEach((num, i) => {
hm[target - num] = i
})
for (let i = 0; i < nums.length; i++) {
if(hm[nums[i]] !== undefined && hm[nums[i]] !== i) {
return ([hm[nums[i]], i])
}
}
};
var twoSum = function(nums, target) {
for (var i = 0; i < nums.length; i++)
{
if( nums.indexOf(target - nums[i]) !== -1)
{
return [i , nums.indexOf(target - nums[i])]
}
}
};
For clearity console a & b in inner for loop . This will give you clear insight
var twoSum = function(nums, target) {
var arr=[];
for(var a=0;a<nums.length;a++){
for(var b=1;b<nums.length;b++){
let c=nums[a]+nums[b];
if(c== target && a != b){
arr[0]=a;
arr[1]=b;
}
}
}
return arr;
};
My solution:
Create a Set
Then loop the array for retrieve all the differences between the target number minus all the elements in array. Insert only which are positive (as is a Set, duplicates will not be included).
Then iterates array again, now only compare if array elements is in the set, if yes take the index from i store in the index array and return it.
public static Object solution(int[] a, int target){
Set<Integer> s = new HashSet<>();
ArrayList<Integer> indexes = new ArrayList<Integer>();
for (int e : a){
Integer diff = new Integer(target - e);
if(diff>0){
s.add(diff);
}
}
int i = 0;
for (int e : a){
if(s.contains(e)){
indexes.add(i);
}
i++;
}
return indexes;
}
def twoSum(self, nums: List[int], target: int) -> List[int]:
for i in range(len(nums)):
comp = target - nums[i]
if comp in nums:
j = nums.index(comp)
if(i!=j):
return [i,j]
var twoSum = function(nums, 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([15, 7, 11, 2],9))
console.log(twoSum([3, 2, 4],6))
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
indx =[]
for i in range(len(nums)):
for j in range(i+1,len(nums)):
if nums[j]==(target-nums[i]):
indx.append(i)
indx.append(j)
return indx
twoSummation = (numsArr, estTarget) => {
for(let index = 0; index < numsArr.length; index++){
for(let n = index+1; n < numsArr.length; n++){
if(numsArr[index] + numsArr[n] == estTarget){
return [index, n]
}
}
}
}
console.log(twoSummation([2,7,11,15], 9))
console.log(twoSummation([3,2,4], 6))
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var twoSum = function(nums, target) {
for(var i=0;i<nums.length;i++){
for(var j=i+1;j<nums.length;j++){
temp = nums[i]+nums[j];
if(temp == target){
return [nums[i],nums[j]]
}
}
}
};
console.log(twoSum([15, 7, 11, 2],9))
console.log(twoSum([3, 2, 4],6))
console.log(twoSum([3,3],6))
</script>
</body>
</html>
Solution from my leetcode submission in Java. Top 75% in runtime, top 25% in memory. It is 0(n) however uses an external HashMap.
import java.util.HashMap;
class Solution {
public int[] twoSum(int[] nums, int target) {
HashMap<Integer, Integer> numbers= new HashMap<Integer, Integer>();
for(int i=0; i<nums.length; i++){
int cur = nums[i];
numbers.put(cur, i);
}
for(int i=0; i<nums.length; i++){
//check map for diff of target - cur
int diff = target - nums[i];
if(numbers.containsKey(diff) && numbers.get(diff)!=i){
return new int[]{i, numbers.get(diff)};
}
}
return null;
}
}

How to code all for all cases of Two Sum javascript problem

I have been working on the two sum problem for the past few hours and can't seem to account for the case where there are only two numbers and their sum is the same as the first number doubled.
The result should be [0,1], but i'm getting [0,0].
let nums = [3,3];
let targetNum = 6;
function twoSum(nums, target) {
for (let i = 0; i < nums.length; i++) {
for (let b = i+1; b < nums.length; b++) {
if ((nums[i] + nums[b]) == target) {
return [nums.indexOf(nums[i]), nums.indexOf(nums[b])];
}
}
}
}
console.log(twoSum(nums, targetNum))
Two Sum
My approach uses a javascript object and completes the algorithm in O(n) time complexity.
const twoSum = (nums, target) => {
let hash = {}
for(i=0;i<nums.length;i++) {
if (hash[nums[i]]!==undefined) {
return [hash[nums[i]], i];
}
hash[target-nums[i]] = i;
}
};
console.log(twoSum([2,7,11,15], 9)); // example
This is not the way to solve the problem. Step through the array and save the complement of the target wrt the number in the array. This will also solve your corner case.
You should consider, indexOf(i) -> start from the first element, returns the index when match found! That is why in your code, nums.indexOf(nums[i]) and nums.indexOf(nums[b]) which is basically 3 in all two cases, it will return 0, cause 3 is the first element in array.
instead of doing this, return the index itself.
let nums = [3,3];
let targetNum = 6;
function twoSum(nums, target) {
for (let i = 0; i < nums.length; i++) {
for (let b = i+1; b < nums.length; b++) {
if ((nums[i] + nums[b]) == target) {
return i + "" +b;
}
}
}
}
console.log(twoSum(nums, targetNum))

Infinity loop with generating random numbers?

I'm working on a script that creates random mathematical problems (simple questions). The problem is that there seems to be an infinite loop, and I can't figure out where or how my script can run without this part of the code.
https://codepen.io/abooo/pen/GyJKwP?editors=1010
var arr = [];
var lastArr = [];
while(lastArr.length<122){
arr.push('<br>'+Math.round(Math.random() * 10)+'+'+Math.round(Math.random() * 10)+'=');
lastArr=removeDuplicates(arr);
}
document.write(lastArr.join(' '));
alert(arr.length);
function removeDuplicates(arr){
let unique_array = []
for(let i = 0;i < arr.length; i++){
if(unique_array.indexOf(arr[i]) == -1){
unique_array.push(arr[i])
}
}
return unique_array
}
This is the working snippet without any infinity loop.
var arr = [];
while(arr.length < 121){
var randValue = '<br>'+Math.round(Math.random() * 10)+'+'+Math.round(Math.random() * 10)+'='
arr.push();
// Check duplicate elements before push
if ( arr.indexOf(randValue) == -1 ) arr.push(randValue);
}
document.write(arr.join(' '));
alert(arr.length);
It looks like you are trying to shuffle every possible outcome of adding two numbers from 0 to 10. Why not do that, rather than your attempt of "throw missiles into pidgeonholes and hope for the best"?
function generateArray(maxA, maxB) {
var arr = [],
a, b;
for (a = 0; a <= maxA; a++) {
for (b = 0; b <= maxB; b++) {
arr.push([a, b]);
}
}
return arr;
}
function shuffleArray(arr) {
// simple Fisher-Yates shuffle, modifies original array
var l = arr.length,
i, j, t;
for (i = l - 1; i > 0; i--) {
j = Math.floor(Math.random() * (i + 1));
t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
}
function outputArray(arr) {
var i, l = arr.length;
for (i = 0; i < l; i++) {
document.write("<br />" + arr[i][0] + " + " + arr[i][1] + " = ");
}
}
var arr = generateArray(10, 10);
shuffleArray(arr);
outputArray(arr);
The line Math.round(Math.random() * 10) will give you 11 possible outcomes (from 0 to 10). That means there are 11*11 non-duplicates lastArr can hold.
As mentioned in the comments, it does not only take a long time for every possibility to occur, it is also impossible for lastArr to be longer than 121 (11*11), which means your loop cannot end, due to the condition while(lastArr.length<122).
Besides that there are better ways to achieve the desired result, changing your code to this will make it work:
var arr = [];
var lastArr = [];
while(lastArr.length<121){ // Here I change 122 to 121
arr.push('<br>'+Math.round(Math.random() * 10)+'+'+Math.round(Math.random() * 10)+'=');
lastArr=removeDuplicates(arr);
}
document.write(lastArr.join(' '));
alert(arr.length);
function removeDuplicates(arr){
let unique_array = []
for(let i = 0;i < arr.length; i++){
if(unique_array.indexOf(arr[i]) == -1){
unique_array.push(arr[i])
}
}
return unique_array
}

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);
/* */

Interleave array elements

What is a fast and simple implementation of interleave:
console.log( interleave([1,2,3,4,5,6] ,2) ); // [1,4,2,5,3,6]
console.log( interleave([1,2,3,4,5,6,7,8] ,2) ); // [1,5,2,6,3,7,4,8]
console.log( interleave([1,2,3,4,5,6] ,3) ); // [1,3,5,2,4,6]
console.log( interleave([1,2,3,4,5,6,7,8,9],3) ); // [1,4,7,2,5,8,3,6,9]
This mimics taking the array and splitting it into n equal parts, and then shifting items off the front of each partial array in sequence. (n=2 simulates a perfect halving and single shuffle of a deck of cards.)
I don't much care exactly what happens when the number of items in the array is not evenly divisible by n. Reasonable answers might either interleave the leftovers, or even "punt" and throw them all onto the end.
function interleave( deck, step ) {
var copyDeck = deck.slice(),
stop = Math.floor(copyDeck.length/step),
newDeck = [];
for (var i=0; i<step; i++) {
for (var j=0; j<stop; j++) {
newDeck[i + (j*step)] = copyDeck.shift();
}
}
if(copyDeck.length>0) {
newDeck = newDeck.concat(copyDeck);
}
return newDeck;
}
It could be done with a counter instead of shift()
function interleave( deck, step ) {
var len = deck.length,
stop = Math.floor(len/step),
newDeck = [],
cnt=0;
for (var i=0; i<step; i++) {
for (var j=0; j<stop; j++) {
newDeck[i + (j*step)] = deck[cnt++];
}
}
if(cnt<len) {
newDeck = newDeck.concat(deck.slice(cnt,len));
}
return newDeck;
}
And instead of appending the extras to the end, we can use ceil and exit when we run out
function interleave( deck, step ) {
var copyDeck = deck.slice(),
stop = Math.ceil(copyDeck.length/step),
newDeck = [];
for (var i=0; i<step; i++) {
for (var j=0; j<stop && copyDeck.length>0; j++) {
newDeck[i + (j*step)] = copyDeck.shift();
}
}
return newDeck;
}
can i has prize? :-D
function interleave(a, n) {
var i, d = a.length + 1, r = [];
for (i = 0; i < a.length; i++) {
r[i] = a[Math.floor(i * d / n % a.length)];
}
return r;
}
according to my tests r.push(... is faster than r[i] = ... so do with that as you like..
note this only works consistently with sets perfectly divisible by n, here is the most optimized version i can come up with:
function interleave(a, n) {
var i, d = (a.length + 1) / n, r = [a[0]];
for (i = 1; i < a.length; i++) {
r.push(a[Math.floor(i * d) % a.length]);
}
return r;
}
O(n-1), can anyone come up with a log version? to the mathmobile! [spinning mathman logo]
Without for loops (I've added some checkup for the equal blocks):
function interleave(arr, blocks)
{
var len = arr.length / blocks, ret = [], i = 0;
if (len % 1 != 0) return false;
while(arr.length>0)
{
ret.push(arr.splice(i, 1)[0]);
i += (len-1);
if (i>arr.length-1) {i = 0; len--;}
}
return ret;
}
alert(interleave([1,2,3,4,5,6,7,8], 2));
And playground :) http://jsfiddle.net/7tC9F/
how about functional with recursion:
function interleave(a, n) {
function f(a1, d) {
var next = a1.length && f(a1.slice(d), d);
a1.length = Math.min(a1.length, d);
return function(a2) {
if (!a1.length) {
return false;
}
a2.push(a1.shift());
if (next) {
next(a2);
}
return true;
};
}
var r = [], x = f(a, Math.ceil(a.length / n));
while (x(r)) {}
return r;
}
Phrogz was pretty close, but it didn't interleave properly. This is based on that effort:
function interleave(items, parts) {
var len = items.length;
var step = len/parts | 0;
var result = [];
for (var i=0, j; i<step; ++i) {
j = i
while (j < len) {
result.push(items[j]);
j += step;
}
}
return result;
}
interleave([0,1,2,3], 2); // 0,2,1,3
interleave([0,1,2,3,4,5,6,7,8,9,10,11], 2) // 0,6,1,7,2,8,3,9,4,10,5,11
interleave([0,1,2,3,4,5,6,7,8,9,10,11], 3) // 0,4,8,1,5,9,2,6,10,3,7,11
interleave([0,1,2,3,4,5,6,7,8,9,10,11], 4) // 0,3,6,9,1,4,7,10,2,5,8,11
interleave([0,1,2,3,4,5,6,7,8,9,10,11], 5) // 0,2,4,6,8,10,1,3,5,7,9,11
Since I've been pushed to add my own answer early (edited to fix bugs noted by RobG):
function interleave(items,parts){
var stride = Math.ceil( items.length / parts ) || 1;
var result = [], len=items.length;
for (var i=0;i<stride;++i){
for (var j=i;j<len;j+=stride){
result.push(items[j]);
}
}
return result;
}
try this one:
function interleave(deck, base){
var subdecks = [];
for(count = 0; count < base; count++){
subdecks[count] = [];
}
for(var count = 0, subdeck = 0; count < deck.length; count++){
subdecks[subdeck].push(deck[count]);
subdeck = subdeck == base - 1? 0 : subdeck + 1;
}
var newDeck = [];
for(count = 0; count < base; count++){
newDeck = newDeck.concat(subdecks[count]);
}
return newDeck;
}

Categories

Resources