[英]Better way to find two array elements that add up to a given number
I wrote this code that works just fine. 我写的这段代码很好用。 However I think there may be a cleaner/better way of doing this. 但是,我认为这样做可能会有更清洁/更好的方法。 Basically I have to create a function that takes 2 arguments (array and sum), and return the 2 elements that when adding them together is equals the sum parameter. 基本上,我必须创建一个接受2个参数(数组和sum)的函数,并返回将两个元素加在一起等于sum参数的2个元素。 Does anyone know how to refactor this code or make it simpler? 有谁知道如何重构该代码或使其更简单?
Here's my code: 这是我的代码:
var list = [2, 6, 20, 4, 11, 30, 5]; var sum = 9; var myArray = []; function findTwoNumbers(arr, sum) { for (var i = 0; i < arr.length; i++) { for (var j = i + 1; j < arr.length; j++) { if (arr[i] + arr[j] === sum) { myArray.push(arr[i], arr[j]); } } } return myArray; } console.log(findTwoNumbers(list, sum)); // [4 , 5]
Your code is O(N^2). 您的代码是O(N ^ 2)。 You can reduce it a bit by using a set (though it has a startup cost of constructing the set, so you probably get raw speedup only for large arrays): 您可以通过使用集合来减少它(尽管它具有构造集合的启动成本,因此您可能仅对大型阵列获得原始加速):
function findTwoNumbers(arr, sum) {
const arrset = new Set(arr);
const answer = arr.find(e => e + e !== sum && arrset.has(sum - e));
return answer === undefined ? null : [answer, sum - answer];
}
Turn the array into a Set. 将数组变成集合。 Then iterate through the array and test whether sum - element
is in the set. 然后遍历数组并测试sum - element
是否在集合中。
I need to check for diff == element
to prevent returning a match from adding an element to itself. 我需要检查diff == element
以防止返回将元素添加到自身的匹配。
var list = [2, 6, 20, 4, 11, 30, 5]; var sum = 9; function findTwoNumbers(arr, sum) { const set = new Set(arr); for (let i = 0; i < arr.length; i++) { let element = arr[i]; let diff = sum - element; if (diff != element && set.has(diff)) { return [element, diff]; } } } console.log(findTwoNumbers(list, sum)); // [4 , 5] console.log(findTwoNumbers([2, 5], 4)); // undefined
You can return an array without the need of external array 您可以返回一个数组,而无需外部数组
function findTwoNumbers(arr, sum){
for (var i = 0; i < arr.length; i++) {
for(var j = i + 1; j < arr.length; j++){
if(arr[i] + arr[j] === sum){
return [arr[i] , arr[j]];
}
}
}
return [];
}
Note: This will only search for the first pair that satisfy the condition, there could be more pairs down the iteration path. 注意:这只会搜索满足条件的第一对,在迭代路径中可能会有更多对。
Another way would be to first sort the array (O(nlog(n)) then traverse the array and for each element, find the difference between (sum - element) and then do a binary search (O(log(n)) for that value. 另一种方法是先对数组(O(nlog(n))排序,然后遍历该数组,然后对每个元素求和(sum-element)之间的差,然后对它进行二进制搜索(O(log(n))那个价值。
For example, the first element is 2, so you would binary search the sorted array for 7 (9 - 2 = 7) and if you find it, then 2 and 7 are a pair. 例如,第一个元素是2,因此您将对排序后的数组进行二进制搜索以找到7(9-2 = 7),如果找到它,则2和7是一对。 You can stop short too as soon as you reach an element that is greater than (sum/2). 一旦达到大于(sum / 2)的元素,您也可以立即做空。
Hope this helps. 希望这可以帮助。
How about this: 这个怎么样:
Basically take the sum and subtract the first number in the array to get the remainder, then check if the remainder exists in the array, if not move on to the next. 基本上取总和并减去数组中的第一个数字以得到余数,然后检查数组中是否存在余数,如果不继续,则移至下一个。
let list = [2, 6, 20, 4, 11, 30, 5]; let sum = 9; function findTwoNumbers(list, sum) { for (let i = 0; i < list.length; i++) { let n =list[i]; if (list.includes(sum - n)) { return [sum - n, n]; } } } console.log(findTwoNumbers(list, sum))
The obvious problem with your code currently as it will return an array of multiple pairs if there is more than one combination to achieve the sum from the input numbers. 当前,您的代码存在明显的问题,因为如果有多个组合可以从输入数字中求和,则它将返回多对数组。 So for example: 因此,例如:
let list = [1, 2, 4, 1];
let sum = 5;
//would give [1, 4, 4, 1];
Assuming you want just the first pair, there's no reason to maintain an array (and certainly not one outside the function) - just return immediately: 假设您只需要第一对,就没有理由维护一个数组(并且肯定不在函数外部)—只需立即返回:
function findTwoNumbers(arr, sum) {
for (let i = 0; i < arr.length; i++)
for (let j = i + 1; j < arr.length; j++)
if (arr[i] + arr[j] === sum)
return [arr[i], arr[j]];
}
There are further efficiencies and simplicities we can make. 我们可以进一步提高效率和简化性。 Firstly, the loop should ignore any number which is, in itself, higher than sum-1 (since this is the highest a number can be to still achieve the sum with the help of another number, which have to be 1.) 首先,循环应该忽略本身大于sum-1的任何数字(因为这是最高的数字,在另一个数字的帮助下仍可以求和,该数字必须为1。)
And since it's midnight, how about some pointless syntax sugar? 既然是午夜,那么一些毫无意义的语法糖又如何呢?
function findTwoNumbers(arr, sum) {
let nums = arr.filter(num => num < sum);
return nums.map(num => {
return nums.filter(num2 => num + num2 == sum)[0];
}).filter(x => x);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.