[解题报告] 《算法零基础100讲》(第28讲) 递推问题


前言

跟着英雄哥打卡第二十八天
[专题跳转->《算法零基础100讲》]
[万人千题社区跳转]


一、斐波那契数

跳转力扣:509. 斐波那契数

难度:★☆☆☆☆

说明:初学者必接触的一道题,最基础的递推问题,数据量小,可水过

代码如下(示例):

class Solution {
public:
    int fib(int n) {
        int f[31];
        f[0] = 0;f[1] = 1;
        for(int i = 2; i <= n; i++){
            f[i] = f[i-1] + f[i-2];
        }
        return f[n];
    }
};

二、第 N 个泰波那契数

跳转力扣:1137. 第 N 个泰波那契数

难度:★☆☆☆☆

说明:类比上一道斐波那契数列,泰波那契数为之升级版,但难度没有变化

代码如下(示例):

class Solution {
public:
    int tribonacci(int n) {
        int t[38];
        t[0] = 0, t[1] = 1, t[2] = 1;
        for (int i = 3; i <= 37; i ++) {
            t[i] = t[i - 1] + t[i - 2] + t[i - 3];
        }
        return t[n];
    }
};

三、杨辉三角

跳转力扣:118. 杨辉三角

难度:★☆☆☆☆

说明:杨辉三角也是初学者入门题,关键为每行第一次元素与主对角线需要赋值为1,其他的数根据头顶的2个数相加递推可以得到

代码如下(示例):

class Solution {
public:
    vector<vector<int>> generate(int numRows) {
        vector<vector<int>> ans(numRows);
        for (int i = 0; i < numRows; i++){
            ans[i].resize(i + 1);
            ans[i][0] = ans[i][i] = 1; // 第一列与主对角线
            for (int j = 1; j < i; j++){
                ans[i][j] = ans[i - 1][j] + ans[i - 1][j - 1]; // 头顶的2个数
            }
        }
        return ans;
    }
};

四、杨辉三角 II

跳转力扣:119. 杨辉三角 II

难度:★☆☆☆☆

说明:与上题不同是,上题需要返回整个二维数组,此题只需要返回需要求的行,换汤不换药

代码如下(示例):

class Solution {
public:
    vector<int> getRow(int rowIndex) {
        vector<vector<int>> ans(rowIndex + 1);
        for (int i = 0; i < rowIndex + 1; i++){
            ans[i].resize(i + 1);
            ans[i][0] = ans[i][i] = 1;
            for (int j = 1; j < i; j++){
                ans[i][j] = ans[i - 1][j] + ans[i - 1][j - 1];
            }
        }
        return ans[rowIndex];
    }
};

五、爬楼梯

跳转力扣:70. 爬楼梯

难度:★☆☆☆☆

说明:斐波那契数的应用,由于爬到x层楼梯的最后一步可能是一步,也可能是两步,因此只需要求出爬x-1楼层的方法数和爬x-2楼层的方法数,相加即可,我们知道爬1楼有1种方法,爬2楼有2种方法,地推可求得爬x层的方法,递推公式如下:f(x)=f(x−1)+f(x−2)

代码如下(示例):

class Solution {
public:
    // 斐波那契数列
    int climbStairs(int n) {
        int p = 0, q = 0, r = 1;
        for(int i = 0; i < n; i++){
            q = p;
            p = r;
            r = p + q;
        }
        return r;
    }
};

六、圆圈中最后剩下的数字

跳转力扣:剑指 Offer 62. 圆圈中最后剩下的数字

难度:★☆☆☆☆

说明:由于在最后一轮删除后剩余最后的人在下标一定是0,可以从此出发往前递推,假设p为最后剩下来的那个人每从往后前每轮的下标(最后下标为0,因此赋值为0),又由于每一次删除一个人后每个剩下的人都往左移m位(超出问题可以用取余解决),因此在往前递推时需要让我们要找的留在最后的人的下标向右平移m位,最终循环结束后停住的下标即为一开始未删除前的下标

代码如下(示例):

class Solution {
public:
    int lastRemaining(int n, int m) {
        int p = 0;
        for (int i = 2; i <= n; i ++) {
            p = (p + m) % i;
        }
        return p;
    }
};

七、翻转字符

跳转力扣:剑指 Offer II 092. 翻转字符

难度:★★☆☆☆

说明:用前缀和解决问题,该题定义的前缀和是该数(不包括该数)前面的数的和,又可表示为前面的1的个数,要使条件成立,需要满足全0,或全1,或前面全0后面全1这三种情况,因此只需要遍历从0到n,让[0,i)的’1’的个数加上[i,n]的’0’的个数,找到的个数即为翻转次数,用minn维护所找的翻转次数最少的值

代码如下(示例):

class Solution {
public:
    int minFlipsMonoIncr(string s) {
        vector<int> s1(s.size() + 1);
        vector<int> s2(s.size() + 1);
        int minn = INT_MAX;
        // [0, i)中1的个数
        for (int i = 0; i < s.size(); i ++) {
            s1[i + 1] = s1[i] + (s[i] == '1');
        }
        // [i, n]中0的个数
        for (int i = 0; i <= s.size(); i ++) {
            s2[i] = (s.size() - i) - (s1[s.size()] - s1[i]);
        }
        for (int i = 0; i <= s.size(); i ++) {
            minn = min(minn, s1[i] + s2[i]);
        }
        return minn;
    }
};
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值