难题是获得制作数字1所需的最少步骤数。允许的操作是
1. You can subtract 1 from the number
2. You can divide the number by 2 if it is divisible by 2.
3. You can divide the number by 3 if it is divisible by 3.
最后,您需要通过执行上述操作来设置数字1。我正在尝试获得一个解决方案,它为我提供了使数字1所需的上述操作的最小数量。 我的代码(用Java编写)如下。
public int minStepsBottomUp(int n) {
int[] memoArray = new int[n+1];
memoArray[0] = 0;
memoArray[1] = 0;
for(int i=2;i<=n;++i){
int r = 1 + memoArray[i-1];
if(n % 2 == 0) {
r = Math.min(r, 1+memoArray[n/2]);
}
if(n % 3 == 0) {
r = Math.min(r, 1+memoArray[n/3]);
}
memoArray[i] = r;
}
return memoArray[n];
}
但是我得到了一些模棱两可的结果。例如 - 如果数字是5,我得到的最小步数为4.实际上它应该是3.有人可以解释我哪里出错吗?
答案 0 :(得分:4)
我建议撤销问题:从1
开始我们应该到达 n
使用三种运营:
例如,对于5
,我们将进行3次操作(乘以3,加1,加1):
1 -> 3 -> 4 -> 5
到目前为止,我们已经有了标准的动态编程问题; C#实现:
private static int Best(int value) {
if (value <= 0)
return -1; // or throw ArgumentOutOfRangeException
else if (value == 1)
return 0;
Dictionary<int, int> best = new Dictionary<int, int>() { {1, 0} };
List<int> agenda = new List<int>() { 1 };
for (int step = 1; ; ++step)
for (int i = agenda.Count - 1; i >= 0; --i) {
int item = agenda[i];
agenda.RemoveAt(i);
int[] next = new int[] { item + 1, item * 2, item * 3 };
foreach (int v in next) {
if (v == value)
return step;
if (!best.ContainsKey(v)) {
best.Add(v, step);
agenda.Add(v);
}
}
}
}
试验:
// 3
Console.WriteLine(Best(5));
// 3
Console.WriteLine(Best(10));
// 7
Console.WriteLine(Best(100));
// 19
Console.WriteLine(Best(1000000));
答案 1 :(得分:3)
在你的循环中,你使用的是n而不是i。
例如,n%2 == 0应为i%2 == 0
答案 2 :(得分:0)
如果数字为5,您可以通过以下方式获得1:
int x = 5 - 1;
x = x - 1;
x= x / 3;