Day18——T70. 爬楼梯、T第39级台阶、T附加.求2的n次方
T70. 爬楼梯
假设你正在爬楼梯。需要 n
阶你才能到达楼顶。
每次你可以爬 1
或 2
个台阶。你有多少种不同的方法可以爬到楼顶呢?
-
动态规划 + 滚动数组
-
滚动数组
滚动数组是一种能够在动态规划中降低空间复杂度的方法
观察dp方程来判断需要使用哪些数据,可以抛弃哪些数据,一旦找到关系,就可以用新的数据不断覆盖旧的数据来减少空间的使用
本题使用滚动数组将空间复杂度从o(n)优化成o(1)
-
动态规划
-
转移公式
爬到第 x 级台阶的方案数是爬到第 x−1 级台阶的方案数和爬到第 x−2 级台阶的方案数的和
f ( x ) = f ( x − 1 ) + f ( x − 2 ) f(x) = f(x - 1) + f(x - 2) f(x)=f(x−1)+f(x−2) -
边界条件
从第 0 级开始爬的,所以从第 0 级爬到第 0 级我们可以看作只有一种方案,即 f(0)=1
从第 0 级到第 1 级也只有一种方案,即爬一级,f(1)=1
f(2)=2
f(3)=3
f(4)=5
-
-
class Solution {
public:
int climbStairs(int n) {
int s, r, t;
//使用滚动数组思想,设定初值
s = 0;
r = 0;
t = 1;//第0级台阶的方法数
for(int i = 1; i <= n; ++i)
{
//不断轮番覆盖
s = r;
r = t;
t = s + r;
}
return t;
}
};
T第39级台阶
参考博客:https://blog.csdn.net/qq_53133234/article/details/122821168
小明刚刚看完电影《第39级台阶》,离开电影院的时候,他数了数礼堂前的台阶数,恰好是39级!
站在台阶前,他突然又想着一个问题:
如果我每一步只能迈上1个或2个台阶。先迈左脚,然后左右交替,最后一步是迈右脚,也就是说一共要走偶数步。那么,上完39级台阶,有多少种不同的上法呢?
请你利用计算机的优势,帮助小明寻找答案。
要求提交的是一个整数。
注意:不要提交解答过程,或其它的辅助说明文字。
-
递归
1.确定递归函数的参数和返回值
2.确定递归终止条件
3.确定单层循环的逻辑
#include<iostream> using namespace std; //surplus是剩余台阶,step是已走的步数 int solve(int surplus,int step){ //surplus到最后只有两种情况,surplus==0 或 surplus == -1, 两个都是结束递归条件 if(surplus<0){ return 0; } if(surplus==0 && step%2==0){//步数一定是个偶数 return 1; } return solve(surplus-1,step+1)+solve(surplus-2,step+1); } int main(){ cout << solve(39,0); return 0; }
-
dp动态规划
odd:奇数even:偶数
dp[n].odd:上到第n级台阶时步数是奇数的方案数
dp[n].even:上到第n级台阶时步数是偶数 的方案数
状态移动方程:第n级台阶一定是从n-1级或是n-2级台阶过来的
dp[n].odd = dp[n-1].even + dp[n-2].even //偶数阶由奇数阶上来 dp[n].even = dp[n-1].odd + dp[n-2].odd//奇数阶由偶数阶上来
输入一个整数n,求2的n次方,n < 10000
-
算法思想:计算比较大的数字,longlong也无法满足时,可以用数组记录,每个数组元素为一位数字
#include<iostream> #include<cmath> using namespace std; int main() { int num[10000] = {1}; int n, next; int len = 1;//记录数字长度 cin >> n; //反向记录结果,数字倒序 while(n --)//促进进位处不断相加 { int next = 0;//重新给每次的进位数置0 for(int i = 0; i < len; ++ i)//乘法运算:对数组中每个数都乘2 { next += num[i] *2;//每次乘2 num[i] = next % 10;//求余保留在原位置 next /= 10;//记录总进位 } if(next)//若进位不为0(next必然在10以内) num[len ++] = next;//则在数组下一个位置记录进位数 } for(int i = len - 1; i >=0; i --)//反向打印数组,即为所求数的正序数 { cout << num[i]; } return 0; }