Day18——T70. 爬楼梯、T第39级台阶、T附加.求2的n次方

Day18——T70. 爬楼梯、T第39级台阶、T附加.求2的n次方

T70. 爬楼梯

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 12 个台阶。你有多少种不同的方法可以爬到楼顶呢?

  • 动态规划 + 滚动数组

    • 滚动数组

      滚动数组是一种能够在动态规划中降低空间复杂度的方法

      观察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(x1)+f(x2)

      • 边界条件

        从第 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;
    }
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值