有n个楼梯,站在底部的人想要到达顶部。该人一次可以爬 1 个楼梯或 2 个楼梯。数一数,人能登顶。
考虑图中所示的示例。 n 的值为 3。有 3 种方法可以到达顶部。该图取自 Easier Fibonacci 谜题
例子:
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
(1, 1, 1, 1), (1, 1, 2), (2, 1, 1), (1, 2, 1), (2, 2)
方法一:第一种方法使用递归技术来解决这个问题。
方法:我们可以很容易地发现上述问题中的递归性质。该人可达到n的任一第(n-1)个楼梯或从第(n-2)个第楼梯楼梯。因此,对于每个楼梯n ,我们尝试找出到达n-1 th st 和n-2 th楼梯的方法数量,并将它们相加以给出n th楼梯的答案。因此,这种方法的表达式是:
ways(n) = ways(n-1) + ways(n-2)
上面的表达式实际上是斐波那契数的表达式,但是有一点需要注意,way(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)
所以我们可以使用斐波那契数的函数来找到 way(n) 的值。以下是上述想法的 C++ 实现。
C++
// C++ program to count number of
// ways to reach Nth stair
#include
using namespace std;
// 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 C
int main()
{
int s = 4;
cout << "Number of ways = " << countWays(s);
return 0;
}
// This code is contributed by shubhamsingh10
C
// C Program to count number of
// ways to reach Nth stair
#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;
}
Java
class stairs {
// A simple recursive program to find
// n'th fibonacci number
static 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
static int countWays(int s)
{
return fib(s + 1);
}
/* Driver program to test above function */
public static void main(String args[])
{
int s = 4;
System.out.println("Number of ways = " + countWays(s));
}
} /* This code is contributed by Rajat Mishra */
Python
# Python program to count
# ways to reach nth stair
# Recursive function to find
# Nth fibonacci number
def fib(n):
if n <= 1:
return n
return fib(n-1) + fib(n-2)
# Returns no. of ways to
# reach sth stair
def countWays(s):
return fib(s + 1)
# Driver program
s = 4
print "Number of ways = ",
print countWays(s)
# Contributed by Harshit Agrawal
C#
// C# program to count the
// number of ways to reach
// n'th stair
using System;
class GFG {
// A simple recursive
// program to find n'th
// fibonacci number
static 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
static int countWays(int s)
{
return fib(s + 1);
}
// Driver Code
static public void Main()
{
int s = 4;
Console.WriteLine("Number of ways = " + countWays(s));
}
}
// This code is contributed
// by akt_mit
PHP
Javascript
C++
// C++ program to count number of ways
// to reach nth stair when a person
// can climb either 1 or 2 stairs at a time
#include
using namespace std;
// 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 code
int main()
{
int s = 4, m = 2;
cout << "Number of ways = " << countWays(s, m);
return 0;
}
// This code is contribute by shubhamsingh10
C
// C program to count number of ways
// to reach nth 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("Number of ways = %d", countWays(s, m));
return 0;
}
Java
class stairs {
// A recursive function used by countWays
static 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
static int countWays(int s, int m)
{
return countWaysUtil(s + 1, m);
}
/* Driver program to test above function */
public static void main(String args[])
{
int s = 4, m = 2;
System.out.println("Number of ways = "
+ countWays(s, m));
}
} /* This code is contributed by Rajat Mishra */
Python
# A program to count the number of ways
# to reach n'th stair
# Recursive function used by countWays
def countWaysUtil(n, m):
if n <= 1:
return n
res = 0
i = 1
while i<= m and i<= n:
res = res + countWaysUtil(n-i, m)
i = i + 1
return res
# Returns number of ways to reach s'th stair
def countWays(s, m):
return countWaysUtil(s + 1, m)
# Driver program
s, m = 4, 2
print "Number of ways =", countWays(s, m)
# Contributed by Harshit Agrawal
PHP
Javascript
C++
// C++ program to count number of ways
// to reach n'th stair when a person
// can climb 1, 2, ..m stairs at a time
#include
using namespace std;
// 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 code
int main()
{
int s = 4, m = 2;
cout << "Number of ways = "
<< countWays(s, m);
return 0;
}
// This code is contributed by shubhamsingh10
C
// A C program to count number of ways
// to reach n'th 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("Number of ways = %d", countWays(s, m));
return 0;
}
Java
// Java program to count number of ways
// to reach n't stair when a person
// can climb 1, 2, ..m stairs at a time
class GFG {
// A recursive function used by countWays
static int countWaysUtil(int n, int m)
{
int res[] = new int[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
static int countWays(int s, int m)
{
return countWaysUtil(s + 1, m);
}
// Driver method
public static void main(String[] args)
{
int s = 4, m = 2;
System.out.println("Number of ways = "
+ countWays(s, m));
}
}
Python
# A program to count the number of
# ways to reach n'th stair
# Recursive function used by countWays
def countWaysUtil(n, m):
# Creates list res with all elements 0
res = [0 for x in range(n)]
res[0], res[1] = 1, 1
for i in range(2, n):
j = 1
while j<= m and j<= i:
res[i] = res[i] + res[i-j]
j = j + 1
return res[n-1]
# Returns number of ways to reach s'th stair
def countWays(s, m):
return countWaysUtil(s + 1, m)
# Driver Program
s, m = 4, 2
print "Number of ways =", countWays(s, m)
# Contributed by Harshit Agrawal
C#
// C# program to count number
// of ways to reach n'th stair when
// a person can climb 1, 2, ..m
// stairs at a time
using System;
class GFG {
// A recursive function
// used by countWays
static int countWaysUtil(int n, int m)
{
int[] res = new int[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
static int countWays(int s, int m)
{
return countWaysUtil(s + 1, m);
}
// Driver Code
public static void Main()
{
int s = 4, m = 2;
Console.WriteLine("Number of ways = "
+ countWays(s, m));
}
}
// This code is contributed by anuj_67.
PHP
Javascript
C++
// A C++ program to count the number of ways
// to reach n'th stair when user
// climb 1 .. m stairs at a time.
// Contributor: rsampaths16
#include
using namespace std;
// Returns number of ways
// to reach s'th stair
int countWays(int n, int m)
{
int res[n + 1];
int temp = 0;
res[0] = 1;
for (int i = 1; i <= n; i++)
{
int s = i - m - 1;
int e = i - 1;
if (s >= 0)
{
temp -= res[s];
}
temp += res[e];
res[i] = temp;
}
return res[n];
}
// Driver Code
int main()
{
int n = 5, m = 3;
cout << "Number of ways = "
<< countWays(n, m);
return 0;
}
// This code is contributed by shubhamsingh10
C
// A C program to count the number of ways
// to reach n'th stair when user
// climb 1 .. m stairs at a time.
// Contributor: rsampaths16
#include
// Returns number of ways
// to reach s'th stair
int countWays(int n, int m)
{
int res[n + 1];
int temp = 0;
res[0] = 1;
for (int i = 1; i <= n; i++) {
int s = i - m - 1;
int e = i - 1;
if (s >= 0) {
temp -= res[s];
}
temp += res[e];
res[i] = temp;
}
return res[n];
}
// Driver Code
int main()
{
int n = 5, m = 3;
printf("Number of ways = %d",
countWays(n, m));
return 0;
}
Java
// Java program to count number of
// ways to reach n't stair when a
// person can climb 1, 2, ..m
// stairs at a time
class GFG{
// Returns number of ways
// to reach s'th stair
static int countWays(int n, int m)
{
int res[] = new int[n + 1];
int temp = 0;
res[0] = 1;
for(int i = 1; i <= n; i++)
{
int s = i - m - 1;
int e = i - 1;
if (s >= 0)
{
temp -= res[s];
}
temp += res[e];
res[i] = temp;
}
return res[n];
}
// Driver Code
public static void main(String[] args)
{
int n = 5, m = 3;
System.out.println("Number of ways = " +
countWays(n, m));
}
}
// This code is contributed by equbalzeeshan
Python3
# Python3 program to count the number
# of ways to reach n'th stair when
# user climb 1 .. m stairs at a time.
# Function to count number of ways
# to reach s'th stair
def countWays(n, m):
temp = 0
res = [1]
for i in range(1, n + 1):
s = i - m - 1
e = i - 1
if (s >= 0):
temp -= res[s]
temp += res[e]
res.append(temp)
return res[n]
# Driver Code
n = 5
m = 3
print('Number of ways =', countWays(n, m))
# This code is contributed by 31ajaydandge
C#
// C# program to count number of
// ways to reach n'th stair when
// a person can climb 1, 2, ..m
// stairs at a time
using System;
class GFG{
// Returns number of ways
// to reach s'th stair
static int countWays(int n, int m)
{
int[] res = new int[n + 1];
int temp = 0;
res[0] = 1;
for(int i = 1; i <= n; i++)
{
int s = i - m - 1;
int e = i - 1;
if (s >= 0)
{
temp -= res[s];
}
temp += res[e];
res[i] = temp;
}
return res[n];
}
// Driver Code
public static void Main()
{
int n = 5, m = 3;
Console.WriteLine("Number of ways = " +
countWays(n, m));
}
}
// This code is contributed by equbalzeeshan
Javascript
C++
#include
using namespace std;
int main() {
int n;
n=5;
// Here n/2 is done to count the number 2's in n
// 1 is added for case where there is no 2.
// eg: if n=4 ans will be 3.
// {1,1,1,1} set having no 2.
// {1,1,2} ans {2,2} (n/2) sets containing 2.
cout<<"Number of ways when order of steps does not matter is : "<<1+(n/2)<
Java
import java.util.*;
class GFG{
public static void main(String[] args)
{
int n;
n = 5;
// Here n/2 is done to count the number 2's
// in n 1 is added for case where there is no 2.
// eg: if n=4 ans will be 3.
// {1,1,1,1} set having no 2.
// {1,1,2} ans {2,2} (n/2) sets containing 2.
System.out.print("Number of ways when order of steps " +
"does not matter is : " + (1 + (n / 2)));
}
}
// This code is contributed by todaysgaurav
Python3
n = 5
# Here n/2 is done to count the number 2's in n
# 1 is added for case where there is no 2.
# eg: if n=4 ans will be 3.
# {1,1,1,1} set having no 2.
# {1,1,2} ans {2,2} (n/2) sets containing 2.
print("Number of ways when order "
"of steps does not matter is : ", 1 + (n // 2))
# This code is contributed by rohitsingh07052
C#
using System;
class GFG{
static public void Main()
{
int n;
n = 5;
// Here n/2 is done to count the number 2's
// in n 1 is added for case where there is no 2.
// eg: if n=4 ans will be 3.
// {1,1,1,1} set having no 2.
// {1,1,2} ans {2,2} (n/2) sets containing 2.
Console.WriteLine("Number of ways when order of steps " +
"does not matter is : " + (1 + (n / 2)));
}
}
// This code is contributed by Ankita saini
Javascript
C++
#include
using namespace std;
typedef vector > matrix;
#define LOOP(i, n) for (int i = 1; i < n; i++)
// Computes A*B
// where A,B are square matrices
matrix mul(matrix A, matrix B, long long MOD = 1000000007)
{
int K = A.size();
matrix C(K, vector(K, 0));
LOOP(i, K)
LOOP(j, K)
LOOP(k, K)
C[i][j] = (C[i][j] + A[i][k] * B[k][j]) % MOD;
return C;
}
// Computes A^n
matrix power(matrix A, long long n)
{
if (n == 1)
return A;
if (n % 2 != 0) {
// n is odd
// A^n = A * [ A^(n-1) ]
A = mul(A, power(A, n - 1));
}
else {
// n is even
// A^n = [ A^(n/2) ] * [ A^(n/2) ]
A = power(A, n / 2);
A = mul(A, A);
}
return A;
}
long long ways(int n)
{
vector F(3);
F[1] = 1;
F[2] = 2;
int K = 2;
long long MOD = 1000000007;
// create K*K matrix
matrix C(K + 1, vector(K + 1, 0));
/*
A matrix with (i+1)th element as 1 and last row
contains constants
[
[0 1 0 0 ... 0]
[0 0 1 0 ... 0]
[0 0 0 1 ... 0]
[. . . . ... .]
[. . . . ... .]
[c(k) c(k-1) c(k-2) ... c1]
]
*/
for (int i = 1; i < K; ++i) {
C[i][i + 1] = 1;
}
// Last row is the constants c(k) c(k-1) ... c1
// f(n) = 1*f(n-1) + 1*f(n-2)
C[K][1] = 1;
C[K][2] = 1;
if (n <= 2)
return F[n];
// f(n) = C^(n-1)*F
C = power(C, n - 1);
long long result = 0;
// result will be the first row of C^(n-1)*F
for (int i = 1; i <= K; ++i) {
result = (result + C[1][i] * F[i]) % MOD;
}
return result;
}
int main()
{
int n = 4;
cout << "Number of ways = " << ways(n) << endl;
}
// This code is contributed by darshang631
C++
#include
using namespace std;
typedef vector > matrix;
#define LOOP(i, n) for (int i = 1; i < n; i++)
// Computes A*B when A,B are square matrices of equal
// dimensions)
matrix mul(matrix A, matrix B, long long MOD = 1000000007)
{
int K = A.size();
matrix C(K, vector(K, 0));
LOOP(i, K)
LOOP(j, K)
LOOP(k, K)
C[i][j] = (C[i][j] + A[i][k] * B[k][j]) % MOD;
return C;
}
matrix power(matrix A, long long n)
{
if (n == 1)
return A;
if (n % 2 != 0) {
// n is odd
// A^n = A * [ A^(n-1) ]
A = mul(A, power(A, n - 1));
}
else {
// n is even
// A^n = [ A^(n/2) ] * [ A^(n/2) ]
A = power(A, n / 2);
A = mul(A, A);
}
return A;
}
vector initialize(vector A)
{
// Initializes the base vector F(1)
int K = A[A.size() - 1]; // Assuming A is sorted
vector F(K + 1, 0);
vector dp(K + 1);
dp[0] = 0;
dp[A[1]] = 1; // There is one and only one way to reach
// first element
F[A[1]] = 1;
for (int i = 2; i < A.size(); ++i) {
// Loop through A[i-1] to A[i] and fill the dp array
for (int j = A[i - 1] + 1; j <= A[i]; ++j) {
// dp[j] = dp[j-A[0]] + .. + dp[j-A[i-1]]
for (int k = 1; k < i; ++k) {
dp[j] += dp[j - A[k]];
}
}
// There will be one more way to reach A[i]
dp[A[i]] += 1;
F[A[i]] = dp[A[i]];
}
return F;
}
long long ways(vector A, int n)
{
int K = A[A.size() - 1]; // Assuming A is sorted
vector F = initialize(A); // O(m^2*K)
int MOD = 1000000007;
// create K*K matrix
matrix C(K + 1, vector(K + 1, 0));
/*
A matrix with (i+1)th element as 1 and last row contains
constants
[
[0 1 0 0 ... 0]
[0 0 1 0 ... 0]
[0 0 0 1 ... 0]
[. . . . ... .]
[. . . . ... .]
[c(k) c(k-1) c(k-2) ... c1]
]
*/
for (int i = 1; i < K; ++i) {
C[i][i + 1] = 1;
}
// Last row is the constants c(k) c(k-1) ... c1
// f(n) = 1*f(n-1) + 1*f(n-2)
for (int i = 1; i < A.size(); ++i) {
C[K][K - A[i] + 1] = 1;
}
if (n <= K)
return F[n];
// F(n) = C^(n-1)*F
C = power(C, n - 1); // O(k^3Log(n))
long long result = 0;
// result will be the first row of C^(n-1)*F
for (int i = 1; i <= K; ++i) {
result = (result + C[1][i] * F[i]) % MOD;
}
return result;
}
int main()
{
int n = 9;
vector A = {
0, 2, 4, 5
}; // 0 is just because we are using 1 based indexing
cout << "Number of ways = " << ways(A, n) << endl;
}
// This code is contributed by darshang631
输出:
Number of ways = 5
复杂度分析:
- 时间复杂度: O(2^n)
由于冗余计算,上述实现的时间复杂度是指数级的(黄金比例增加到 n 次方)。可以使用前面讨论的 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 的楼梯。
以下是上述递归的实现。
C++
// C++ program to count number of ways
// to reach nth stair when a person
// can climb either 1 or 2 stairs at a time
#include
using namespace std;
// 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 code
int main()
{
int s = 4, m = 2;
cout << "Number of ways = " << countWays(s, m);
return 0;
}
// This code is contribute by shubhamsingh10
C
// C program to count number of ways
// to reach nth 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("Number of ways = %d", countWays(s, m));
return 0;
}
Java
class stairs {
// A recursive function used by countWays
static 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
static int countWays(int s, int m)
{
return countWaysUtil(s + 1, m);
}
/* Driver program to test above function */
public static void main(String args[])
{
int s = 4, m = 2;
System.out.println("Number of ways = "
+ countWays(s, m));
}
} /* This code is contributed by Rajat Mishra */
Python
# A program to count the number of ways
# to reach n'th stair
# Recursive function used by countWays
def countWaysUtil(n, m):
if n <= 1:
return n
res = 0
i = 1
while i<= m and i<= n:
res = res + countWaysUtil(n-i, m)
i = i + 1
return res
# Returns number of ways to reach s'th stair
def countWays(s, m):
return countWaysUtil(s + 1, m)
# Driver program
s, m = 4, 2
print "Number of ways =", countWays(s, m)
# Contributed by Harshit Agrawal
PHP
Javascript
输出:
Number of ways = 5
复杂度分析:
- 时间复杂度: O(2^n)
由于冗余计算,上述实现的时间复杂度是指数级的(黄金比例提高到 n 次方)。可以使用动态规划将其优化为 O(m*n)。 - 辅助空间: O(1)
方法 2 :该方法使用动态规划技术来得出解决方案。
方法:我们使用以下关系以自下而上的方式创建一个表res[] :
res[i] = res[i] + res[i-j] for every (i-j) >= 0
使得阵列的第i个指数将包含的路的数目需要达到第i个步骤考虑攀登的所有可能性(即,从1到i)。
下面的代码实现了上述方法:
C++
// C++ program to count number of ways
// to reach n'th stair when a person
// can climb 1, 2, ..m stairs at a time
#include
using namespace std;
// 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 code
int main()
{
int s = 4, m = 2;
cout << "Number of ways = "
<< countWays(s, m);
return 0;
}
// This code is contributed by shubhamsingh10
C
// A C program to count number of ways
// to reach n'th 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("Number of ways = %d", countWays(s, m));
return 0;
}
Java
// Java program to count number of ways
// to reach n't stair when a person
// can climb 1, 2, ..m stairs at a time
class GFG {
// A recursive function used by countWays
static int countWaysUtil(int n, int m)
{
int res[] = new int[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
static int countWays(int s, int m)
{
return countWaysUtil(s + 1, m);
}
// Driver method
public static void main(String[] args)
{
int s = 4, m = 2;
System.out.println("Number of ways = "
+ countWays(s, m));
}
}
Python
# A program to count the number of
# ways to reach n'th stair
# Recursive function used by countWays
def countWaysUtil(n, m):
# Creates list res with all elements 0
res = [0 for x in range(n)]
res[0], res[1] = 1, 1
for i in range(2, n):
j = 1
while j<= m and j<= i:
res[i] = res[i] + res[i-j]
j = j + 1
return res[n-1]
# Returns number of ways to reach s'th stair
def countWays(s, m):
return countWaysUtil(s + 1, m)
# Driver Program
s, m = 4, 2
print "Number of ways =", countWays(s, m)
# Contributed by Harshit Agrawal
C#
// C# program to count number
// of ways to reach n'th stair when
// a person can climb 1, 2, ..m
// stairs at a time
using System;
class GFG {
// A recursive function
// used by countWays
static int countWaysUtil(int n, int m)
{
int[] res = new int[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
static int countWays(int s, int m)
{
return countWaysUtil(s + 1, m);
}
// Driver Code
public static void Main()
{
int s = 4, m = 2;
Console.WriteLine("Number of ways = "
+ countWays(s, m));
}
}
// This code is contributed by anuj_67.
PHP
Javascript
输出:
Number of ways = 5
复杂度分析:
- 时间复杂度: O(m*n)
- 辅助空间: O(n)
方法三:第三种方法使用滑动窗口的技术来得出解决方案。
方法:该方法有效地实现了上述动态规划方法。
在第i个楼梯的这种方法中,我们保留了最后m 个可能的楼梯总和的窗口,我们可以从中爬到第i个楼梯。我们没有运行内循环,而是将内循环的结果保存在一个临时变量中。我们删除前一个窗口的元素并添加当前窗口的元素并更新总和。
下面的代码实现了上面的想法
C++
// A C++ program to count the number of ways
// to reach n'th stair when user
// climb 1 .. m stairs at a time.
// Contributor: rsampaths16
#include
using namespace std;
// Returns number of ways
// to reach s'th stair
int countWays(int n, int m)
{
int res[n + 1];
int temp = 0;
res[0] = 1;
for (int i = 1; i <= n; i++)
{
int s = i - m - 1;
int e = i - 1;
if (s >= 0)
{
temp -= res[s];
}
temp += res[e];
res[i] = temp;
}
return res[n];
}
// Driver Code
int main()
{
int n = 5, m = 3;
cout << "Number of ways = "
<< countWays(n, m);
return 0;
}
// This code is contributed by shubhamsingh10
C
// A C program to count the number of ways
// to reach n'th stair when user
// climb 1 .. m stairs at a time.
// Contributor: rsampaths16
#include
// Returns number of ways
// to reach s'th stair
int countWays(int n, int m)
{
int res[n + 1];
int temp = 0;
res[0] = 1;
for (int i = 1; i <= n; i++) {
int s = i - m - 1;
int e = i - 1;
if (s >= 0) {
temp -= res[s];
}
temp += res[e];
res[i] = temp;
}
return res[n];
}
// Driver Code
int main()
{
int n = 5, m = 3;
printf("Number of ways = %d",
countWays(n, m));
return 0;
}
Java
// Java program to count number of
// ways to reach n't stair when a
// person can climb 1, 2, ..m
// stairs at a time
class GFG{
// Returns number of ways
// to reach s'th stair
static int countWays(int n, int m)
{
int res[] = new int[n + 1];
int temp = 0;
res[0] = 1;
for(int i = 1; i <= n; i++)
{
int s = i - m - 1;
int e = i - 1;
if (s >= 0)
{
temp -= res[s];
}
temp += res[e];
res[i] = temp;
}
return res[n];
}
// Driver Code
public static void main(String[] args)
{
int n = 5, m = 3;
System.out.println("Number of ways = " +
countWays(n, m));
}
}
// This code is contributed by equbalzeeshan
蟒蛇3
# Python3 program to count the number
# of ways to reach n'th stair when
# user climb 1 .. m stairs at a time.
# Function to count number of ways
# to reach s'th stair
def countWays(n, m):
temp = 0
res = [1]
for i in range(1, n + 1):
s = i - m - 1
e = i - 1
if (s >= 0):
temp -= res[s]
temp += res[e]
res.append(temp)
return res[n]
# Driver Code
n = 5
m = 3
print('Number of ways =', countWays(n, m))
# This code is contributed by 31ajaydandge
C#
// C# program to count number of
// ways to reach n'th stair when
// a person can climb 1, 2, ..m
// stairs at a time
using System;
class GFG{
// Returns number of ways
// to reach s'th stair
static int countWays(int n, int m)
{
int[] res = new int[n + 1];
int temp = 0;
res[0] = 1;
for(int i = 1; i <= n; i++)
{
int s = i - m - 1;
int e = i - 1;
if (s >= 0)
{
temp -= res[s];
}
temp += res[e];
res[i] = temp;
}
return res[n];
}
// Driver Code
public static void Main()
{
int n = 5, m = 3;
Console.WriteLine("Number of ways = " +
countWays(n, m));
}
}
// This code is contributed by equbalzeeshan
Javascript
输出:
Number of ways = 13
复杂度分析:
- 时间复杂度: O(n)
- 辅助空间: O(n)
方法 4 :第四种方法使用简单的数学方法,但这仅适用于在计算步数时(顺序无关紧要)的问题。
方法:在这种方法中,我们简单地计算具有 2 的集合的数量。
C++
#include
using namespace std;
int main() {
int n;
n=5;
// Here n/2 is done to count the number 2's in n
// 1 is added for case where there is no 2.
// eg: if n=4 ans will be 3.
// {1,1,1,1} set having no 2.
// {1,1,2} ans {2,2} (n/2) sets containing 2.
cout<<"Number of ways when order of steps does not matter is : "<<1+(n/2)<
Java
import java.util.*;
class GFG{
public static void main(String[] args)
{
int n;
n = 5;
// Here n/2 is done to count the number 2's
// in n 1 is added for case where there is no 2.
// eg: if n=4 ans will be 3.
// {1,1,1,1} set having no 2.
// {1,1,2} ans {2,2} (n/2) sets containing 2.
System.out.print("Number of ways when order of steps " +
"does not matter is : " + (1 + (n / 2)));
}
}
// This code is contributed by todaysgaurav
蟒蛇3
n = 5
# Here n/2 is done to count the number 2's in n
# 1 is added for case where there is no 2.
# eg: if n=4 ans will be 3.
# {1,1,1,1} set having no 2.
# {1,1,2} ans {2,2} (n/2) sets containing 2.
print("Number of ways when order "
"of steps does not matter is : ", 1 + (n // 2))
# This code is contributed by rohitsingh07052
C#
using System;
class GFG{
static public void Main()
{
int n;
n = 5;
// Here n/2 is done to count the number 2's
// in n 1 is added for case where there is no 2.
// eg: if n=4 ans will be 3.
// {1,1,1,1} set having no 2.
// {1,1,2} ans {2,2} (n/2) sets containing 2.
Console.WriteLine("Number of ways when order of steps " +
"does not matter is : " + (1 + (n / 2)));
}
}
// This code is contributed by Ankita saini
Javascript
输出:
Number of ways when order of steps does not matter is : 3
复杂度分析:
- 时间复杂度: O(1)
- 空间复杂度: O(1)
注意:此方法只适用于Count way to N’th Stair(Order not matter)的问题。
顺序无关紧要意味着 n = 4 {1 2 1} ,{2 1 1} , {1 1 2}被认为是相同的。
方法5:该方法使用矩阵求幂的技术来得出解决方案。
方法:到达第n个楼梯(顺序很重要)的方法数等于到达第(n-1)个楼梯和第(n-2)个楼梯的方法数之和
这对应于以下递推关系:
f(n) = f(n-1) + f(n-2)
f(1) = 1
f(2) = 2
其中 f(n) 表示到达第n个楼梯的方式数
笔记:
f(1) = 1 因为只有 1 种方法可以到达 n=1 楼梯 {1}
f(2) = 2 因为有 2 种方法可以到达 n=2 楼梯 {1,1} , {2}
它是一种具有常系数的线性递推关系,我们可以使用矩阵求幂方法来解决它们,该方法基本上为给定递推关系找到一个变换矩阵,然后将该变换重复应用于基向量以获得解)。
F(n) = CN-1F(1)
where
C is the transformation matrix
F(1) is the base vector
F(n) is the desired solution
因此,对于我们的情况,变换矩阵 C 将是:
0 | 1 |
1 | 1 |
C N-1可以使用分而治之技术计算,在 O( (K^3) Log n) 中,其中 K 是 C 的维度
和 F(1):
1 |
2 |
例如,对于 n= 4:
F(4) = C 3 F(1)
C 3 =
1 | 2 |
2 | 3 |
因此,C 3 F(1) =
5 |
8 |
C++
#include
using namespace std;
typedef vector > matrix;
#define LOOP(i, n) for (int i = 1; i < n; i++)
// Computes A*B
// where A,B are square matrices
matrix mul(matrix A, matrix B, long long MOD = 1000000007)
{
int K = A.size();
matrix C(K, vector(K, 0));
LOOP(i, K)
LOOP(j, K)
LOOP(k, K)
C[i][j] = (C[i][j] + A[i][k] * B[k][j]) % MOD;
return C;
}
// Computes A^n
matrix power(matrix A, long long n)
{
if (n == 1)
return A;
if (n % 2 != 0) {
// n is odd
// A^n = A * [ A^(n-1) ]
A = mul(A, power(A, n - 1));
}
else {
// n is even
// A^n = [ A^(n/2) ] * [ A^(n/2) ]
A = power(A, n / 2);
A = mul(A, A);
}
return A;
}
long long ways(int n)
{
vector F(3);
F[1] = 1;
F[2] = 2;
int K = 2;
long long MOD = 1000000007;
// create K*K matrix
matrix C(K + 1, vector(K + 1, 0));
/*
A matrix with (i+1)th element as 1 and last row
contains constants
[
[0 1 0 0 ... 0]
[0 0 1 0 ... 0]
[0 0 0 1 ... 0]
[. . . . ... .]
[. . . . ... .]
[c(k) c(k-1) c(k-2) ... c1]
]
*/
for (int i = 1; i < K; ++i) {
C[i][i + 1] = 1;
}
// Last row is the constants c(k) c(k-1) ... c1
// f(n) = 1*f(n-1) + 1*f(n-2)
C[K][1] = 1;
C[K][2] = 1;
if (n <= 2)
return F[n];
// f(n) = C^(n-1)*F
C = power(C, n - 1);
long long result = 0;
// result will be the first row of C^(n-1)*F
for (int i = 1; i <= K; ++i) {
result = (result + C[1][i] * F[i]) % MOD;
}
return result;
}
int main()
{
int n = 4;
cout << "Number of ways = " << ways(n) << endl;
}
// This code is contributed by darshang631
Number of ways = 5
复杂度分析:
- 时间复杂度:O(Log n)
- 空间复杂度:O(1)
问题的概括:
给定一个包含所有有效步骤的数组 A {a1, a2, …., am},计算到达第n个楼梯的方法数。 (顺序很重要)
例子:
Input:
A = [1,2]
n = 4
Output: 5
Explanation:
This is the given problem, i.e, count the number of ways to reach n=4 stairs with climbing 1 or 2 stairs at a time
Therefore, ways will be: {1,1,1,1} {1,1,2} {1,2,1} {2,1,1} {2,2} = 5
Input:
A = [2,4,5]
n = 9
Output: 5
Explanation:
There are 5 ways to reach n=9 stairs with climbing 2 or 4 or 5 stairs at a time
Therefore, ways will be: {5,4} {4,5} {2,2,5} {2,5,2} {5,2,2} = 5
方法:
到达第 n 级楼梯的路数由以下递推关系给出
设 K 为 A 中最大的元素。
Step1:计算基向量 F(1)(由 f(1) …. f(K) 组成)
它可以使用动态规划方法在 O(m 2 K) 时间内完成,如下所示:
我们以 A = {2,4,5} 为例。为了计算 F(1) = { f(1), f(2), f(3), f(4), f(5) } 我们将维护一个初始为空的数组并迭代地将 A i附加到它,对于每个A i我们会找到到达 [A i-1 , 到 A i, ] 的方法数
因此对于 A = {2 ,4 ,5}
设 T 为初始空数组
Iteration 1: T = {2} n = {1,2} dp = {0,1} (Number of ways to reach n=1,2 with steps given by T)
Iteration 2: T = {2,4} n = {1,2,3,4} dp = {0,1,0,2} (Number of ways to reach n=1,2,3,4 with steps given by T)
Iteration 3: T = {2,4,5} n = {1,2,3,4,5} dp = {0,1,0,2,1} (Number of ways to reach n=1,2,3,4,5 with steps given by T)
注意:由于已经计算了一些值(迭代 2 的 1,2 等)我们可以在循环中避免它们
在所有迭代之后,dp 数组将是:[0,1,0,2,1]
因此,A = [2,4,5] 的基向量 F(1) 是:
0 |
1 |
0 |
2 |
1 |
现在我们有了基向量 F(1),C(变换矩阵)的计算很容易
第二步:计算C,变换矩阵
它是一个具有元素 A i,i+1 = 1 且最后一行包含常量的矩阵
现在可以通过 A 中该元素的存在来确定常数
因此,对于 A = [2,4,5] 常量将是 c = [1,1,0,1,0](如果 (K-i+1) 存在于 A 中,则 C i = 1,否则为 0,其中 1 <= i <= K )
因此,A =[2,4,5] 的变换矩阵 C 是:
0 | 1 | 0 | 0 | 0 |
0 | 0 | 1 | 0 | 0 |
0 | 0 | 0 | 1 | 0 |
0 | 0 | 0 | 0 | 1 |
1 | 1 | 0 | 1 | 0 |
第 3 步:计算 F(n)
要计算 F(n),使用以下公式:
F(n) = Cn-1F(1)
现在我们有了 C 和 F(1) 我们可以使用分而治之的技术来找到 C n-1 ,从而找到所需的输出
C++
#include
using namespace std;
typedef vector > matrix;
#define LOOP(i, n) for (int i = 1; i < n; i++)
// Computes A*B when A,B are square matrices of equal
// dimensions)
matrix mul(matrix A, matrix B, long long MOD = 1000000007)
{
int K = A.size();
matrix C(K, vector(K, 0));
LOOP(i, K)
LOOP(j, K)
LOOP(k, K)
C[i][j] = (C[i][j] + A[i][k] * B[k][j]) % MOD;
return C;
}
matrix power(matrix A, long long n)
{
if (n == 1)
return A;
if (n % 2 != 0) {
// n is odd
// A^n = A * [ A^(n-1) ]
A = mul(A, power(A, n - 1));
}
else {
// n is even
// A^n = [ A^(n/2) ] * [ A^(n/2) ]
A = power(A, n / 2);
A = mul(A, A);
}
return A;
}
vector initialize(vector A)
{
// Initializes the base vector F(1)
int K = A[A.size() - 1]; // Assuming A is sorted
vector F(K + 1, 0);
vector dp(K + 1);
dp[0] = 0;
dp[A[1]] = 1; // There is one and only one way to reach
// first element
F[A[1]] = 1;
for (int i = 2; i < A.size(); ++i) {
// Loop through A[i-1] to A[i] and fill the dp array
for (int j = A[i - 1] + 1; j <= A[i]; ++j) {
// dp[j] = dp[j-A[0]] + .. + dp[j-A[i-1]]
for (int k = 1; k < i; ++k) {
dp[j] += dp[j - A[k]];
}
}
// There will be one more way to reach A[i]
dp[A[i]] += 1;
F[A[i]] = dp[A[i]];
}
return F;
}
long long ways(vector A, int n)
{
int K = A[A.size() - 1]; // Assuming A is sorted
vector F = initialize(A); // O(m^2*K)
int MOD = 1000000007;
// create K*K matrix
matrix C(K + 1, vector(K + 1, 0));
/*
A matrix with (i+1)th element as 1 and last row contains
constants
[
[0 1 0 0 ... 0]
[0 0 1 0 ... 0]
[0 0 0 1 ... 0]
[. . . . ... .]
[. . . . ... .]
[c(k) c(k-1) c(k-2) ... c1]
]
*/
for (int i = 1; i < K; ++i) {
C[i][i + 1] = 1;
}
// Last row is the constants c(k) c(k-1) ... c1
// f(n) = 1*f(n-1) + 1*f(n-2)
for (int i = 1; i < A.size(); ++i) {
C[K][K - A[i] + 1] = 1;
}
if (n <= K)
return F[n];
// F(n) = C^(n-1)*F
C = power(C, n - 1); // O(k^3Log(n))
long long result = 0;
// result will be the first row of C^(n-1)*F
for (int i = 1; i <= K; ++i) {
result = (result + C[1][i] * F[i]) % MOD;
}
return result;
}
int main()
{
int n = 9;
vector A = {
0, 2, 4, 5
}; // 0 is just because we are using 1 based indexing
cout << "Number of ways = " << ways(A, n) << endl;
}
// This code is contributed by darshang631
Number of ways = 5
复杂度分析:
Time Complexity: O( m2K + K3Logn )
where
m is the size of Array A
K is the largest element in A
n denotes the stair number (nth stair)
Space Complexity: O(K2)
笔记:
当 n 对于迭代来说太大时,这种方法是理想的
例如:当 (1 ≤ n ≤ 10 9 ) 和 (1 ≤ m,k ≤ 10 2 ) 时考虑这种方法
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。