【发布时间】:2021-12-19 22:42:39
【问题描述】:
我正在尝试编写一种算法,该算法将找到给定整数的最大完美平方,并尽可能快地每次从总数中减去它们的值。这有点难以解释,对于有点模棱两可的标题,我深表歉意,所以我将给出一些输入/输出示例:
- 输入:23
- 输出:[16、4、1、1、1]
- 解释:25 (5x5) 太大,但 16 (4x4) 适合。将其添加到数组中并从 23 (7) 中减去 16。下一个适合的最大完美正方形是 4 (2x2),因此将其添加到数组中并从 7 (3) 中减去 4。从这里开始,最大的完美正方形就是 1 (1x1)。所以将 1 添加到数组中,直到我们得到 0。
- 输入:13
- 输出:[9, 4]
- 解释:9 (3x3) 是最大的正方形,因此将其添加到数组中并从 13 (4) 中减去。那么 4 也是一个完美的正方形,所以添加它并在那里结束。
我的解决方案如下(变量名称与向我提出问题的方式相关):
public static int[] solution(int startingSquareYards) {
ArrayList<Integer> largestSquares = new ArrayList<Integer>();
// Cast for use with Math. methods
double remainingSquareYards = (double) startingSquareYards;
while (remainingSquareYards > 0) {
double largestSquareRoot = Math.floor(Math.sqrt(remainingSquareYards));
// Edit - used to be:
// double yardsOfMaterialUsed = Math.pow(largestSquareRoot, 2);
double yardsOfMaterialUsed = largestSquareRoot * largestSquareRoot;
remainingSquareYards -= yardsOfMaterialUsed;
largestSquares.add((int) yardsOfMaterialUsed);
}
int[] solutionArray = largestSquares.stream().mapToInt(i -> i).toArray();
return solutionArray;
}
我正在征求对我的解决方案的意见,以及我是否可以针对时间/空间复杂性、简单性(同时保持易于阅读/理解)等以任何方式对其进行优化。它目前适用于我做过的所有测试写但我可能缺少边缘情况或改进它的地方 - 输入startingSquareYards可以在1到1,000,000之间。感谢任何建设性的反馈:)
感谢收看!
【问题讨论】:
-
如果您的代码有效,那么这个问题属于Code Review
-
提示 1:
pow(x, 2)很慢。替换为简单的x*x -
提示 2:
sqrt很慢。如果您使用非常大的startingSquareYards,那么也许用正方形填充ArrayList<int>,并找到最接近(但小于)remainingSquareYards(向后遍历)。缓存列表中的最后一个索引,以便在下一次迭代中从那里开始。 -
您的问题是实施回溯。考虑 32。这是 16 和 16,但您的算法会找到 25、4、1、1、1。要快速找到 any 解决方案,只需返回全 1。要找到最小削减,您需要back track。另见Dijkstra
-
考虑这个 48 - 这里有多种可能形成 48 但你的答案应该是什么? [16,16,16] 或 [25,26,4,1,1,1] 或 [36,9,1,1,1] 或 [36,4,1,1,1,1,1,1 ,1,1]
标签: java arrays algorithm optimization perfect-square