例如,如果您有一个数组[20、6、7、8、50],并且如果我传递值21,则它应该返回[6,7,8]此子数组。注意:数字的总和应按顺序。
[20, 6, 7, 8, 50]
21 - [6, 7, 8]
13 - [6, 7]
50 - [] - because it is not in sequence
我尝试了但没用
function sumoftwonumer(arr, s) {
let hashtable = {}
let sum = []
for(let i=0; i<arr.length; i++) {
let innerRequiredValue = s - arr[i]
if(hashtable[innerRequiredValue.toString()] !== undefined) {
sum.push([arr[i], innerRequiredValue])
}
hashtable[innerRequiredValue.toString()] = arr[i]
}
console.log(hashtable)
return sum
}
答案 0 :(得分:2)
您可以尝试使用嵌套的for循环。最坏情况下的时间复杂度为O(n^2)
。确保看到第二种方法更有效。
let arr = [20, 6, 7, 8, 50]
function findNums(arr,sum){
let temp = 0;
for(let i = 0;i<arr.length;i++){
temp = arr[i];
for(let j = i+1;j<arr.length;j++){
temp += arr[j];
if(temp === sum) return arr.slice(i,j+1);
if(temp > sum) break;
}
}
return [];
}
console.log(findNums(arr,21))
console.log(findNums(arr,13))
console.log(findNums(arr,50))
更好的解决方案是创建变量temp
的方法。开始一个接一个地添加元素。当它大于给定的总和时,则从数组的开头删除该元素。
let arr = [20, 6, 7, 8, 50]
function findNums(arr,sum){
let temp = arr[0];
let low = 0;
for(let i = 1;i<arr.length;i++){
temp += arr[i];
if(temp === sum) return arr.slice(low,i+1);
while(temp > sum){
temp -= arr[low]
low++;
}
}
return [];
}
console.log(findNums(arr,21))
console.log(findNums(arr,13))
console.log(findNums(arr,50))
负数的问题在于,当temp
(当前总和)大于给定总和时,我们无法从开始删除元素,因为在数组后可能会有如此负数,这可能使{{1 }}小于或等于
对于负数,您需要创建一个对象来跟踪已经计算出的子数组总和。
temp
答案 1 :(得分:1)
根据您的使用方式,一种可能性是按照尝试尝试的方式进行操作,并创建部分和的哈希表,然后返回一个函数,该函数将在该哈希表中查找您的值。在这里,我这样做了,使函数变成咖喱状,这样您就不必进行每次调用都为一组数字创建哈希图的所有工作。
初始呼叫为O(n^2)
,但后续呼叫仅为O(1)
。如果要在同一组数字上搜索多个值,则此样式很有用。如果您只需要搜索一个值,那么像Maheer Ali的答案中的第二个那样的技术会更有效。
const range = (lo, hi) => [...Array (hi - lo) ]
.map ( (_, i) => lo + i )
const sum = (nbrs) =>
nbrs .reduce ( (a, b) => a + b, 0 )
const findSequentialSum = (nbrs) => {
const subtotals = range (0, nbrs .length)
.flatMap (
i => range (i + 2, nbrs .length + 1)
.map (j => nbrs .slice (i, j) )
)
// .reduce((a, b) => a.concat(b), [[]])
.reduce (
(a, sub, _, __, tot = sum(sub) ) => ({
...a,
[tot]: a [tot] || sub
}),
{}
)
return (total) => subtotals [total] || []
}
const nbrs = [20, 6, 7, 8, 50]
const search = findSequentialSum (nbrs)
console .log (
search (21), //~> [6, 7, 8]
search (13), //~> [6, 7]
search (50), //~> []
)
这两个辅助函数应该很简单:range(3, 10) //=> [3, 4, 5, 6, 7, 8, 9]
和sum([2, 5, 10]) //=> 17
如果您的环境中有flatMap
isn't available,则可以替换
.flatMap (
i => range (i + 2, nbrs .length + 1)
.map (j => nbrs .slice (i, j) )
)
使用
.map (
i => range (i + 2, nbrs .length + 1)
.map (j => nbrs .slice (i, j) )
)
.reduce((a, b) => a.concat(b), [[]])
此外,这里的2
i => range (i + 2, nbrs .length + 1)
要求序列的长度至少为两个。如果您想让50
返回[50]
(对我来说似乎更合逻辑),那么您可以将2
替换为1
。或者,如果您只想查找长度为5或更大的子序列,则可以用更大的替换它。
最后,如果您想返回添加到总数中的 all 个子序列,则将是一个简单的修改,替换为:
[tot]: a [tot] || sub
使用
[tot]: (a [tot] || []).concat([sub])