在某些情况下,一个逻辑的最小步骤失败

时间:2017-05-03 04:59:44

标签: java algorithm dynamic-programming

难题是获得制作数字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.有人可以解释我哪里出错吗?

3 个答案:

答案 0 :(得分:4)

我建议撤销问题:1开始我们应该到达 n使用三种运营:

  • 添加1
  • 乘以2
  • 乘以3

例如,对于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;
相关问题