【问题标题】:Efficient algorithm for getting from 1 to n with 3 specific operations通过 3 个特定操作从 1 到 n 的高效算法
【发布时间】:2016-06-09 16:43:43
【问题描述】:

问题:

鉴于这 3 个对数字和整数 n 的有效操作:

  • 数字加 1
  • 将数字乘以 2
  • 将数字乘以 3

描述一个有效的算法,用上面提到的 3 个操作从 1 到 n 的最小操作数。

例如,对于 n = 28,答案是 4:1 * 3 * 3 * 3 + 1 = 27 + 1 = 28。

我用java写了下面的代码,对于num>=1000需要很长时间才能结束。你能帮我理解w.r.t有什么问题吗?效率。我正在尝试制定更有效的算法来解决问题。请帮忙。

public static int ToN(int num){
    return to(1,num);
}
public static int to(int x,int y){
    if (x==y)
        return 0;
    if (x>y)
        return y;
    return Math.min(Math.min(to(x+1,y),to(x*2,y)),to(x*3,y))+1;
}

【问题讨论】:

  • 你了解过朴素的递归斐波那契实现吗?为什么这么慢?出于同样的原因,您的代码很慢。

标签: algorithm dynamic-programming number-theory


【解决方案1】:

动态规划

使用以前计算的结果来计算新的结果。这使得解决方案是线性的,而不是在您的情况下是指数的。

Python 程序

import sys
n = int(raw_input())
dp = [sys.maxint]*(n+1)
dp[1] = 1

for i in xrange(2, n+1):
    dp[i] = dp[i-1]+1
    if i%2==0:    dp[i] = min(dp[i], dp[i/2]+1)
    if i%3==0:    dp[i] = min(dp[i], dp[i/3]+1)

print dp[n]

【讨论】:

    【解决方案2】:

    您的解决方案很慢,因为您没有缓存以前计算的结果(i

    public static int ToN(int num){
        int[] opsRequired = new int[num+1];
        opsRequired[1] = 1;
        for (int i=2; i <= num; i++) {
             opsRequired[i] = opsRequired[i-1];
             if (i % 2 == 0)
                 opsRequired[i] = Math.min(opsRequired[i], opsRequired[i/2]);
             if (i % 3 == 0)
                 opsRequired[i] = Math.min(opsRequired[i], opsRequired[i/3]);
             opsRequired[i]++;
        }
    }
    

    【讨论】:

      【解决方案3】:

      你可以反省的两件事:

      1)为什么你的递归方法需要两个参数?如果问题始终涉及从 1 到 n 的移动,我们可以只用一个参数来管理。请注意,在递归时,您按原样传递 y(并且您也不会在方法中对 y 的值进行操作)。这通常表明参数本身是多余的。
      2)优化参数后,我们现在可以memoize解决方案。这将大大加快您的方法。

      【讨论】:

        【解决方案4】:

        对于正整数,乘以 3 总是比乘以 2 快,而乘以 2 总是比加 1 快。所以算法很简单。

        if x == y return 0
        if x <= y/3 return 1 + to(x*3,y)
        if x <= y/2 return 1 + to(x*2,y)
        return y-x
        

        【讨论】:

          猜你喜欢
          • 2020-06-12
          • 1970-01-01
          • 1970-01-01
          • 2023-03-28
          • 2012-07-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多