您能否提出解决以下问题的任何算法思路:
给出正整数 S , K ≤ N 。查找不同的正整数 x 1 , x 2 ,..., x K 这样
x 1 2 + x 2 2 + ... + x K 2 = S
x i ≤ N 和 x 对于所有 i = 1的i < x i +1 K 。
到目前为止,我知道我应该开始在 S 的平方根下方搜索最大的 x 。
答案 0 :(得分:1)
这里是稍微优化的蛮力。正如我在评论中(和近距离投票)所链接的那样,在我看来,我们可以修改标准子集和问题以使用正方形。
JavaScript代码(输出末尾的省略号表示将其余的数字加到1):
function f(S, K, N){
function g(s, k, n, c){
const minS = k*(k+1)*(2*k+1)/6;
const maxN = Math.min(
n,
~~Math.sqrt(s - (k-1)*k*(2*k-1)/6)
);
if (s < minS || maxN < 1)
return [];
else if (s == minS)
return [c.concat([k, '...'])];
if (k == 0)
return [];
return g(s - maxN*maxN, k - 1, maxN - 1, c.slice().concat(maxN))
.concat(
g(s, k, maxN - 1, c)
);
}
return g(S, K, N, []);
}
for (let j=1; j<6; j++)
console.log(JSON.stringify([178, j, f(178, j, 100)]));
console.log(JSON.stringify([178, 5, f(178, 5, 10)]));
答案 1 :(得分:1)
由于您要的是算法主意,而不是确切的答案,所以这是我的2美分。
您可以通过查找从1, 4, 9, 16, 25...
到1
的所有理想平方(例如S
)并将其放入{{1} }。
然后,如果您可以解决以下(更一般的)问题,则可以轻松解决原始问题。
一般问题:
给定一个任意集PerfectSquareSetLessThanS
,找到V
的一个子集W
,其子集正好具有V
个数字,使得它们的总和为K
。
虽然我还没有一个精确的解决方案,但是您的一般问题看起来很像一个众所周知的问题,称为3SUM问题。
3SUM问题询问是否给定一组S
数字,是否存在3个数字之和,它们的总和为0。Wikipedia页面概述了一种搜索这种连音的算法。
请注意,3SUM问题具有不同的变式,其中一个是k-SUM(在上段中用k替换3),另一个是非零和变式。也许您可以找到这两种变体的组合来构建通用解决方案。