我认为嵌套循环在这里不会对您有所帮助;您正在进入递归领域。 :-)
您要问的问题基本上可以归结为这一点。你有一个数字列表,以及这些数字的频率。你想想出所有独特的方法,你可以选择每个数字的一定数量的副本。例如,给定
2 2
3 4
5 2
你会想要的
20 30 50
20 30 52
20 32 50
20 32 52
20 34 50
20 34 52
22 30 50
22 30 52
22 32 50
22 32 52
22 34 50
22 34 52
如果我们只写指数,那么我们有
0 0 0
0 0 2
0 2 0
0 2 2
0 4 0
0 4 2
2 0 0
2 0 2
2 2 0
2 2 2
2 4 0
2 4 2
所以问题是如何生成这个。幸运的是,有一个非常漂亮的递归公式可以生成这些数字。它是这样的。我们想编写一个函数AllSquares,它接收一组素数及其重数的列表,然后返回所有可能的乘积,这些乘积可以由那些完全平方的素数组成。我们会以归纳方式进行。
作为我们的基本情况,如果您将空列表提供给AllSquares,则恰好有一个平方积,即 1,即空列表元素的空积。
对于归纳步骤,假设我们有一个非空列表,其第一个元素是 (prime, multiplicity),其余元素是“rest”。假设我们递归地计算通过在列表的其余元素上调用AllSquares 形成的列表“组合”。那么对于 i = 0, 2, 4, ..., 多重性,如果您将列表中的元素乘以 basei,您将得到一个新的完美正方形列表.如果你将所有这些值结合起来,你最终会得到所有可以从数字中形成的完美正方形。很酷的一点是,即使重数是奇数,它也能工作,因为您只考虑偶数指数。
这里有一些实现该算法的简单 Java 代码。它根本没有效率,但它明白了这一点:
private static List<Integer> allSquares(List<BaseMultiplicity> elems) {
/* Base case: If the list is empty, there's only one square. */
if (elems.isEmpty()) {
return Collections.singletonList(1);
}
/* Recursive case: Compute the answer for the rest of the list. */
List<BaseMultiplicity> rest = new LinkedList<BaseMultiplicity>(elems);
rest.remove(0);
List<Integer> recResult = allSquares(rest);
/* Now, for each even power of this number, add appropriately-scaled
* copies of the recursive solution to the result.
*/
List<Integer> result = new ArrayList<Integer>();
for (int i = 0, base = 1; i < elems.get(0).multiplicity;
i += 2, base *= elems.get(0).prime)
for (Integer elem: recResult)
result.add(elem * base * base);
return result;
}
希望这会有所帮助!