前言
跟着英雄哥打卡第二十八天
[专题跳转->《算法零基础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;
}
};
六、圆圈中最后剩下的数字
难度:★☆☆☆☆
说明:由于在最后一轮删除后剩余最后的人在下标一定是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;
}
};
七、翻转字符
难度:★★☆☆☆
说明:用前缀和解决问题,该题定义的前缀和是该数(不包括该数)前面的数的和,又可表示为前面的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;
}
};