📌  相关文章
📜  C程序计算到达第n个楼梯的方式

📅  最后修改于: 2021-05-28 05:26:32             🧑  作者: Mango

有n个楼梯,一个站在底部的人想到达顶部。此人可以一次爬1阶或2阶。数一数,人就可以达到顶峰。

楼梯

考虑图中所示的示例。 n的值是3。有3种方法可以到达顶部。该图取自更简单的斐波那契难题
例子:

Input: n = 1
Output: 1
There is only one way to climb 1 stair

Input: n = 2
Output: 2
There are two ways: (1, 1) and (2)

Input: n = 4
Output: 5
There are five ways: (1, 1, 1, 1), (1, 1, 2), 
(2, 1, 1), (1, 2, 1), (2, 2)

方法1递归。

方法:在上述问题中,我们可以轻松地找到递归性质。人可以从(n-1)楼梯或从第(n-2)楼梯到达n楼梯。因此,对于每个楼梯N,我们试图找出方法来达到N-1楼梯和n-2楼梯,并添加他们给n楼梯答案的数量。因此,这种方法的表达式为:

ways(n) = ways(n-1) + ways(n-2)

上面的表达式实际上是斐波那契数的表达式,但是有一点要注意,Ways(n)的值等于fibonacci(n + 1)。

ways(1) = fib(2) = 1
ways(2) = fib(3) = 2
ways(3) = fib(4) = 3

为了更好地理解,让我们参考下面的递归树:

Input: N = 4

                  fib(5)
           '3'  /        \   '2'
               /          \
           fib(4)         fib(3)
     '2'  /      \ '1'   /      \  
         /        \     /        \ 
     fib(3)     fib(2)fib(2)      fib(1) 
     /    \ '1' /   \ '0'
'1' /   '1'\   /     \ 
   /        \ fib(1) fib(0) 
fib(2)     fib(1)


因此,我们可以使用斐波那契数的函数来查找Ways(n)的值。

以下是上述想法的实现。

// A C program to count number of
// ways to reach n't stair when
// a person can climb 1, 2, ..m stairs at a time.
#include 
  
// A simple recursive program to find
// n'th fibonacci number
int fib(int n)
{
    if (n <= 1)
        return n;
    return fib(n - 1) + fib(n - 2);
}
  
// Returns number of ways to reach s'th stair
int countWays(int s)
{
    return fib(s + 1);
}
  
// Driver program to test above functions
int main()
{
    int s = 4;
    printf("Number of ways = %d", countWays(s));
    getchar();
    return 0;
}
输出:
Number of ways = 5

复杂度分析:

    时间复杂度: O(2 ^ n)。
  1. 与上述方法一样,我们正在执行多余的计算,例如发现fib(3)的次数超过’1’。这将其时间复杂度提高到了指数级。
  2. 可以使用前面讨论的Fibonacci函数优化将其优化为O(Logn)时间。

辅助空间: O(1)。
由于没有使用额外的数据结构来存储值,因此:

上述问题的概括
如果一个人可以在给定的值m上爬上m个楼梯,该如何计算路数。
例如,如果m为4,则该人可以一次爬1阶或2阶或3阶或4阶。

方法:对于以上方法的概括,我们可以使用以下递归关系。
我们可以将重复写成如下形式。

ways(n, m) = ways(n-1, m) + ways(n-2, m) + 
             ... + ways(n-m, m) 

在这种到达楼梯“ n”的方法中,我们尝试从当前楼梯爬上所有小于等于“ n”的楼梯。

// A C program to count number of
// ways to reach n't stair when
// a person can climb either 1 or 2
// stairs at a time
#include 
  
// A recursive function used by countWays
int countWaysUtil(int n, int m)
{
    if (n <= 1)
        return n;
    int res = 0;
    for (int i = 1; i <= m && i <= n; i++)
        res += countWaysUtil(n - i, m);
    return res;
}
  
// Returns number of ways to reach s'th stair
int countWays(int s, int m)
{
    return countWaysUtil(s + 1, m);
}
  
// Driver program to test above functions-
int main()
{
    int s = 4, m = 2;
    printf("Nuber of ways = %d", countWays(s, m));
    return 0;
}
输出:
Nuber of ways = 5

复杂度分析:

  • 时间复杂度: O(2 ^ n)。
    1. 与上述方法一样,我们正在执行冗余计算,例如发现fib(3,2)的次数超过“ 1”,这将其时间复杂度提高到了指数级。
    2. 可以使用动态编程将其优化为O(m * n)。我们以自底向上的方式构建表’res []’。
  • 辅助空间: O(1)。
    o使用任何数据结构来存储值。

方法2动态编程。

方法:该方法使用动态编程技术来解决。

方法:我们使用以下关系以自底向上的方式创建表res []

res[i] = res[i] + res[i-j] for every (i-j) >= 0

使得阵列的i指数将包含的路的数目需要达到i步骤考虑攀登的所有可能性(即,从1到i)。

下面的代码实现了上述方法:

// A C program to count number
// of ways to reach n't stair when
// a person can climb 1, 2, ..m
// stairs at a time
#include 
  
// A recursive function used by countWays
int countWaysUtil(int n, int m)
{
    int res[n];
    res[0] = 1;
    res[1] = 1;
    for (int i = 2; i < n; i++) {
        res[i] = 0;
        for (int j = 1; j <= m && j <= i; j++)
            res[i] += res[i - j];
    }
    return res[n - 1];
}
  
// Returns number of ways to reach s'th stair
int countWays(int s, int m)
{
    return countWaysUtil(s + 1, m);
}
  
// Driver program to test above functions
int main()
{
    int s = 4, m = 2;
    printf("Nuber of ways = %d", countWays(s, m));
    return 0;
}
输出:
Nuber of ways = 5

复杂度分析:

  • 时间复杂度: O(m * n)。
    对于每个楼梯,我们检查所有可能性“ m”,楼梯数为“ n”。
  • 辅助空间: O(n)。
    使用数组存储中间值。

请参阅有关到达第n个楼梯的计数方法的完整文章,以了解更多详细信息!

想要从精选的最佳视频中学习和练习问题,请查看《基础知识到高级C的C基础课程》。