目录
台阶问题
题目描述:
有 N 级台阶,你一开始在底部,每次可以向上迈 1∼K 级台阶,问到达第 N 级台阶有多少种不同方式。输入N K。输出到达N阶台阶的方法。
1.规律法
台阶问题实际上就是斐波那契数列的进阶问题,其中蕴含某种规律,发现这种规律问题就会变得很简单了
观察上图表中数据,假设每次最多可以走的台阶数量为k,不难发现前k项数据是没有规律的,但是从第k项后每一项的数据等于前k项的和。
同时这也意味着,如果k的值过大,需要初始化的项就会较多,所以这种解法仅限k值较小或途中的k值单一且明确的情况下,可以考虑一试。
下面以k=3为例展示代码
int k=3;
int cls(int n)
{
vector<int>a(n+1,0)
a[0]=1;
a[1]=2;
a[3]=4
for(int i=4;i<=n;++i)
{
a[i]=a[i-1]+a[i-2]+a[i-3];
}
return a[n];
}
2.动态规划
思想与上一个方法有点类似,但是该方法具有普遍性,适应任何情况
思想:根据分类计数原理,按照最后一次上台阶的阶数分类,可为N-1次时上一阶,N-2次时上两节……最多到N-K次时上K阶,于是第N次的方法就为N-1,N-2,……,N-K次之和;这也就意味着要算N的方法种类数量,就要算出前N-1项的方法种类数量。
用函数表示就是F(N)=F(N-1)+F(N-2)+…+F(2)+F(1)。
int k = 3;//这里的k值可以任意变换,亦可以当做输入值传入函数
int cls(int n)
{
vector<int>a(n+1, 0);
for (int i = 1; i <= n; ++i)
{
if (i <= k) a[i] = 1;//小于等于k的台阶都有一种一步走到台阶的方法
for (int j = 1; j < i && j <= k; ++j)
a[i] += a[i - j];//将i级台阶分成走N-1级和走1级……走N-k和走k级
}
return a[n];
}
3.DFS算法
这种方法相对比较暴力,如果k值较大开辟的栈帧空间就会很大,但是它的优点也十分明显
那就是代码量小好理解。
int ans=0;
void dfs(int N)
{
if (N == 0)//代表当前步数刚好走到N级台阶
{
ans++;
return;
}
if (N < 0)//代表当前步数越过了N级台阶
return;dfs(N - 1);
dfs(N - 2);
dfs(N - 3);……
dfs(N-k);
}
三种方法讲完了,本人最推荐第二种解法,适应能力强, 没什么特别大的缺点。