1 + 2的所有组合,添加到n

时间:2015-08-25 11:33:56

标签: java algorithm recursion

我正在努力解决这个问题,作为编程面试的准备工作:

  

青蛙只向前移动,但它可以步长1英寸或跳跃2英寸长。青蛙可以使用不同的步骤和跳跃组合覆盖相同的距离。

     

编写一个函数,计算青蛙可以用来覆盖给定距离的不同组合的数量。

     

例如,可以通过三种方式覆盖3英寸的距离:步进步骤,步进跳跃和跳跃步骤。

我认为这有一个非常简单的解决方案,但我似乎无法找到它。我想使用递归,但我不知道如何。以下是我到目前为止的情况:

public class Frog {

    static int combinations = 0;
    static int step = 1;
    static int jump = 2;
    static int[] arr = {step, jump};

    public static int numberOfWays(int n) {
        for (int i = 0; i < arr.length; i++) {
            int sum = 0;
            sum += arr[i];
            System.out.println("SUM outer loop: " + sum + " : " + arr[i]);
            while (sum != 3) {
                for (int j = 0; j < arr.length; j++) {
                    if (sum + arr[j] <= 3) {
                        sum += arr[j];
                        System.out.println("SUM inner loop: " + sum + " : " + arr[j]);
                        if (sum == 3) {
                            combinations++;
                            System.out.println("Combinations " + combinations);
                        }
                    }
                }
            }
        }
        return combinations;
    }

    public static void main(String[] args) {
        System.out.println(numberOfWays(3));
    }
}

它找不到所有组合,我认为代码非常糟糕。任何人都能很好地解决这个问题吗?

6 个答案:

答案 0 :(得分:8)

认为你有一个知道如何解决问题的神谕小问题&#34;你只需要用较小的问题来解决问题。这是递归方法。

在你的情况下,你解决foo(n),通过分割青蛙在最后一步可以做的可能动作,并总结它们:

foo(n) = foo(n-1) + foo(n-2)
            ^         ^
         1 step    2 steps

此外,您需要foo(0) = 1, foo(1)=1的停止条款(单向移动0或1英寸)。

这个递归公式看起来很熟悉吗?你能比天真的递归解决方案更好地解决它吗?

<强>扰流:

<子> <子> Fibonacci Sequence

答案 1 :(得分:1)

这是一个应该有效的简单伪代码实现:

var results = []
function plan(previous, n){
    if (n==0) {
        results.push(previous)
    } else if (n > 0){
        plan(previous + ' step', n-1)
        plan(previous + ' hop', n-2)
    }
}
plan('', 5)

如果您想提高此类算法的效率,可以考虑使用memoization

答案 2 :(得分:1)

以下是组合方式:将n视为1 + 1 + 1 ... = n。现在成对地聚集1,逐渐增加聚集1的数量,总结安排它们的可能性。

例如,将5视为1 1 1 1 1

one bunch   => (1) (1) (1) (11) => 4 choose 1 possibilities to arrange one 2 with three 1's
two bunches => (1) (11) (11)    => 3 choose 2 possibilities to arrange two 2's with one 1
etc.

这似乎与维基百科对斐波那契数字“数学中的使用”的描述直接相关,例如,计算“总和为给定总数n的1和2的成分数”(http://en.wikipedia.org/wiki/Fibonacci_number)。

答案 3 :(得分:1)

这个逻辑工作正常。 (递归)

public static int numberOfWays(int n) {
    if (n== 1) {
        return 1; // step
    } else if (n== 2) {
        return 2; // (step + step) or jump
    } else {
        return numberOfWays(n- 1)
                + numberOfWays(n- 2);
    }
}

答案 4 :(得分:0)

对于较大的集合,已接受的答案未通过性能测试。这是一个带有for循环的版本,可以满足testdome的性能测试。

using System;

public class Frog
    {
    public static int NumberOfWays (int n)
        {
        int first = 0, second = 1;
        for ( int i = 0; i<n; i++ )
            {
            int at = first;
            first = second;
            second = at + second;
            }
        return second;
        }
    public static void Main (String[] args)
        {
        Console.WriteLine (NumberOfWays (3));
        }
    }

答案 5 :(得分:0)

C++ 代码运行良好。

   static int numberOfWays(int n)
   {
      if (n == 1) return 1;
      else if (n == 2) return 2;
      else
      {
        static std::unordered_map<int,int> m;

        auto i = m.find(n);

        if (i != m.end())
           return i->second;

        int x = numberOfWays(n - 1) + numberOfWays(n - 2);

        m[n] = x;

        return x;
      }
   }