我写的这段代码很好用。但是,我认为可能有一种更清洁/更好的方法。基本上,我必须创建一个接受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]
答案 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);
}