我处理了一个问题,你会得到一系列数字和一个目标总和,找到一对总和达到目标数的数字是你的工作。这是我使用简单嵌套for循环的解决方案:
function findPairForSum(integers, target) {
var output = [];
for (var i = 0; i < integers.length; i++) {
for (var j = 0; j < integers.length; j++) {
if (i !== j && integers[i] + integers[j] === target) {
output.push(integers[i], integers[j]);
return output;
}
}
}
return 'not possible';
}
findPairForSum([3, 34, 4, 12, 5, 2], 9); // --> [4, 5]
我的问题是,是否有更简洁的方法来使用更高阶函数编写此解决方案(也许是forEach?)
这是我尝试使用forEach:
function findPairForSum(integers, target) {
var output = [];
integers.forEach(function(firstNum) {
integers.forEach(function(secondNum) {
if (firstNum + secondNum === target) {
output.push(firstNum, secondNum);
}
})
})
if (output === []) {
return 'not possible';
}
return output;
}
findPairForSum([3, 34, 4, 12, 5, 2], 9); // --> [ 4, 5, 5, 4 ]
我尝试在两次推送后返回,但它没有返回任何东西。所以相反,我把回报放在最后。
为什么在最初的两次推送后它会回来?我希望它停在那里,只推两个数字。相反,通过将回报放在最后,它推了4个数字。它应该是[4,5],但我得到了类似[4,5,5,4]的内容。
非常感谢任何建议和帮助!
答案 0 :(得分:2)
假设我们有一组数字,我们必须找到2个数字的子集,其总和为9
:
Numbers: 4, 5, 6
您当前的代码会使用i
和j
从0
到length
进行迭代。这意味着以下迭代符合条件:
Indices: 0, 1, 2
Numbers: 4, 5, 6 // (i) (j)
---------------- // ↓ ↓
i j // Numbers[0] + Numbers[1] === 9
j i // Numbers[1] + Numbers[0] === 9
如您所见,数字4和5在两次迭代中匹配两次:
i === 0 && j === 1
i === 1 && j === 0
您可以通过确保满足一个简单条件来避免这种情况:
j
必须始终大于i
通过在内部j
循环中使用i + 1
初始化for
,可以满足此条件:
for (var i = 0; i < integers.length; i++) {
for (var j = i + 1; j < integers.length; j++) {
// ...
}
}
这样,当j
为0
时,i
永远不会是1
,因为内部for循环将在i
之前运行完成再次增加。一旦发生这种情况,就会创建一个全新的内部for循环,其中j
再次设置为i + 1
。结果如下图所示:
Indices: 0, 1, 2
Numbers: 4, 5, 6
----------------
i j
X i // ← j can never be 0 if (i === 1),
// so the same set is never evaluated twice.
换句话说,最多只检查i
和j
的以下组合:
Indices: 0, 1, 2
----------------
i j
i j
i j
是否有更简洁的方法来使用更高阶函数编写此解决方案(也许是forEach?)
for循环实际上是一个很好的解决方案。在您第一次找到有效数字对后,它们允许您提前中断。另一方面,forEach
或其他数组迭代器函数将一直持续到访问所有设置索引为止。
您实际上是在第一个示例中使用语句return output;
当您对一组包含多个有效集的数字使用forEach
时,您将始终收回所有涉及的数字:
Indices: 0, 1, 2, 3
Numbers: 4, 5, 6, 3 // (i) (j)
------------------- // ↓ ↓
i j // Numbers[0] + Numbers[1] === 4 + 5 === 9
i j // Numbers[2] + Numbers[3] === 6 + 3 === 9
forEach
,map
,reduce
等不允许您提前休息。以下代码段演示了上图中的此问题:< / p>
function findPairForSum(integers, target) {
var output = [];
integers.forEach(function(firstNum, i) {
// slice(i + 1) has the same effect as for (var j = i + 1; ...)
integers.slice(i + 1).forEach(function(secondNum, j) {
if (firstNum + secondNum === target) {
// There is no way here to stop the iteration of either
// forEach call... T_T
output.push(firstNum, secondNum);
}
});
})
if (output.length) {
return output;
}
return 'not possible';
}
console.log(findPairForSum([4, 5, 6, 3], 9)); // --> [4, 5, 6, 3]
这就是为什么我强烈建议坚持使用这个特定用例的for循环。使用for循环,只要遇到一组有效的数字,就可以像return
一样:
function findPairForSum(integers, target) {
for (var i = 0; i < integers.length; i++) {
for (var j = i + 1; j < integers.length; j++) {
if (integers[i] + integers[j] === target) {
return [integers[i], integers[j]];
}
}
}
return 'not possible';
}
console.log(findPairForSum([4, 5, 6, 3], 9)); // --> [4, 5]
答案 1 :(得分:1)
问题是,你从内部循环的数组开始迭代。您可以使用从外部循环的索引处开始加一个的副本,并在找到的值的早期退出。
但这并不能解决多对问题。结果完全错了。
function findPairForSum(integers, target) {
var output = [];
integers.forEach(function(firstNum, i) {
integers.slice(i + 1).some(function(secondNum) {
if (firstNum + secondNum === target) {
output.push(firstNum, secondNum);
return true;
}
});
});
return output.length && output || 'not possible';
}
// console.log(findPairForSum([3, 34, 4, 12, 5, 2], 9));
console.log(findPairForSum([3, 34, 4, 4, 12, 5, 2, 4, 5], 9));
&#13;
对于解决方案,您需要记住使用哪些对。此方法仅使用一个循环和哈希表来计算缺失值。
如果找到一对,则计数器递减,并将两个值推送到结果集。
function findPairForSum(integers, target) {
var hash = Object.create(null),
output = [];
integers.forEach(function(value) {
if (hash[value]) {
output.push(target - value, value);
hash[value]--;
return;
}
hash[target - value] = (hash[target - value] || 0) + 1;
});
return output.length && output || 'not possible';
}
console.log(findPairForSum([3, 34, 4, 4, 12, 5, 2, 4, 5], 9));
&#13;
答案 2 :(得分:1)
这可能是您的解决方案:
function findPairForSum(arr, sum) {
var pairs = [];
arr.forEach(n1 => {
var n2 = arr.find(n2 => n1 + n2 == sum)
if (n2) pairs.push([n1, n2]);
});
return pairs;
}
var sums = findPairForSum([3, 34, 4, 12, 6, 2], 9);
console.log(sums)
&#13;
答案 3 :(得分:0)
这是预料之中的,因为您没有比较索引
此内部数组应仅循环遍历大于外部索引的索引
您可以通过在forEach
的回调函数中使用第二个参数index来实现此目的:
const ints = [3, 34, 4, 12, 5, 6, 2];
function findPairForSum(integers, target) {
let result;
integers.forEach((val1, idx1) => {
integers.forEach((val2, idx2) => {
if (idx1 < idx2 && val1 + val2 === target) {
result = [val1, val2];
}
})
})
return result;
}
console.log(findPairForSum(ints, 9));
&#13;
答案 4 :(得分:0)
您可以使用 Array.prototype.some
,只要条件成立,它就会停止执行。见下面的代码。
function findPairForSum(arr, sum) {
var pairs = [];
arr.some(n1 => {
var n2 = arr.find(n2 => n1 + n2 == sum)
if (n2) {
pairs.push(n1, n2); return true;
};
return false;
});
return pairs.length > 0 ? pairs : "not possible";
}
console.log(findPairForSum([3, 34, 4, 12, 7, 2], 9));
答案 5 :(得分:0)
使用reduce
数组进入另一个数字等于目标value
的数据:
const ints = [3, 34, 4, 12, 6, 2];
const value = 9;
const resp = ints.reduce((acc, ele, idx, self) => {
let found = self.find(x => x + ele == value)
return found ? [found, ele] : acc;
}, []);
console.log(resp); // [3, 6]
&#13;