在给定的整数N上,我们可以使用以下操作:
如何找到在最少步骤中达到1的策略?
答案 0 :(得分:4)
有快速动态编程解决方案: -
minSteps(N) = Minimum(minSteps(N/3),minSteps(N/2),minSteps(N-1)) + 1
注意:如果N不能被3或2整除,则不要将其包含在DP等式中。
时间复杂度: O(N)
空间复杂性: O(N)
DP解决方案的Java代码: -
public static int decompose(int n) {
int steps [] = new int[n+1];
steps[1] = 0;
for(int i=2;i<=n;i++) {
int min = n;
if(i%2==0) {
min = Math.min(min,steps[i/2]);
}
if(i%3==0) {
min = Math.min(min,steps[i/3]);
}
min = Math.min(min,steps[i-1]);
steps[i] = min + 1;
}
int k =n;
System.out.println("Steps:");
while(k>1) {
if(k%3==0&&steps[k/3]+1==steps[k]) {
System.out.println("div 3");
k=k/3;
}
else if(n%2==0&&steps[k/2]+1==steps[k]) {
System.out.println("div 2");
k=k/2;
}
else {
System.out.println("minus 1");
k=k-1;
}
}
return(steps[n]);
}
答案 1 :(得分:4)
正如mbeckish所提到的,你可以将其视为BFS遍历,与自下而上的DP方法相比,它具有明显更好的时间和空间复杂性。您还可以在遍历中应用分类和绑定(B&amp; B)类型的启发式,以便在我们之前已经看到标记值的节点处修剪树的分支。与实际的B&amp; B启发式算法不同,这不会删除最优解决方案,因为它不涉及最佳解决方案可能在何处的任何有根据的猜测。我将给出一个可视化示例,并将算法减少到0以更好地说明。
这是一个完整的操作树,减少10到0:
--------10---------
5 -----9----
---4--- -3- ------8------
2 -3- 1 2 --4-- 7
1 1 2 0 1 2 -3- -----6------
0 0 1 0 1 1 2 2 -3- 5
0 0 0 1 1 1 2 --4--
0 0 0 1 2 -3-
0 1 1 2
0 0 1
0
由于我们正在进行BFS,我们实际上会停留在第一个零点,如下所示,而不是构建树的更深层部分:
--------10------
5 -----9--------
---4--- -3- ------8------
2 -3- 1 2 4 7
1 1 2 0
然而,我们可以通过B&amp; B启发式进一步减少分支的数量,看起来像这样(,这对大量数字产生了巨大的影响):
--------10------
5 -----9--------
4 3 8
2 1 7
0
时间复杂度: O(log n)
空间复杂性: O(log n)
(我认为)
下面是输入为1 googol(10 ^ 100)的python 3代码,在我的计算机上运行大约需要8秒,大约350 MB的RAM。您也可以在https://repl.it/B3Oq/76
在线投放from collections import deque
def number_of_steps(i):
Q = deque()
seen_before = set()
steps = 0
Q.append((i, steps))
while True:
j, steps = Q.popleft()
if j == 1:
return steps
if j % 3 == 0:
branch(Q, seen_before, steps, j // 3)
if j % 2 == 0:
branch(Q, seen_before, steps, j // 2)
branch(Q, seen_before, steps, j - 1)
def branch(Q, seen_before, steps, k):
if k not in seen_before:
seen_before.add(k)
Q.append((k, steps + 1))
import time
n = 10**100
print('input:', n)
start = time.time()
steps = number_of_steps(n)
end = time.time()
print('runtime (seconds):', end - start)
print('number of steps:', steps)
答案 2 :(得分:0)
将此视为广度优先树遍历。
根节点是N.操作是通向其子节点的边缘,
当你达到1时停止。
从根到1的路径是解决方案。