查找两个加起来等于给定数字的数组元素的更好方法

时间:2019-06-14 22:38:32

标签: javascript

我写的这段代码很好用。但是,我认为可能有一种更清洁/更好的方法。基本上,我必须创建一个接受2个参数(数组和sum)的函数,并返回将两个元素加在一起等于sum参数的2个元素。有谁知道如何重构该代码或使其更简单?

这是我的代码:

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]

6 个答案:

答案 0 :(得分:3)

您的代码为O(N ^ 2)。您可以通过使用一个集合来减少它(尽管它具有构造集合的启动成本,因此您可能仅对大型阵列获得原始加速):

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];
}

答案 1 :(得分:2)

将数组变成Set。然后遍历数组并测试sum - element是否在集合中。

我需要检查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

答案 2 :(得分:1)

您可以返回一个数组,而无需外部数组

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 [];
}

注意:这只会搜索满足条件的第一对,沿着迭代路径可能会有更多对。

答案 3 :(得分:0)

另一种方法是先对数组进行排序(O(nlog(n))然后遍历该数组,然后为每个元素找到(sum-element)之间的差,然后进行二进制搜索(O(log(n ))。

例如,第一个元素是2,因此您将对排序后的数组进行二进制搜索以找到7(9-2 = 7),如果找到它,则2和7是一对。一旦达到大于(sum / 2)的元素,您也可以立即做空。

希望这会有所帮助。

答案 4 :(得分:0)

如何?

基本上取总和并减去数组中的第一个数字以得到余数,然后检查数组中是否存在余数,如果不存在则移至下一个。

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))

答案 5 :(得分:0)

当前代码存在明显的问题,因为如果有多个组合可以从输入数字中求和,则它将返回多对数组。例如:

let list = [1, 2, 4, 1];
let sum = 5;
//would give [1, 4, 4, 1];

假设您只需要第一对,就没有理由维护一个数组(并且肯定不在函数外部)—只需立即返回:

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]];
}

我们可以进一步提高效率和简化性。首先,循环应该忽略本身大于sum-1的任何数字(因为这是最高的数字,因此仍然可以借助另一个必须为1的数字来求和)。

既然是午夜,那么一些毫无意义的语法糖呢?

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);
}