解题报告
1.力扣剑指 Offer II 098. 路径的数目
原题链接
源码剖析
class Solution {
public:
int uniquePaths(int m, int n) {
int dp[m][n];
int i,j;
for(i = 0 ; i<m ; ++i ){
dp[i][0] = 1;
}
for(i = 0 ; i < n ; ++i ) {
dp[0][i] = 1;
}
for(i = 1; i < m ; ++i ) {
for( j = 1 ; j < n ; ++j ) {
dp[i][j] = dp[i-1][j] + dp[i][j-1];
}
}
return dp[m-1][n-1];
}
};
这题可以使用动态规划来解决,按照如下几个步骤:设计状态->写出状态转移方程->设定初始状态->执行状态转移->返回结果;
- 设计状态:到达每一格的方案数即为状态 dp[i][j] ;
- 写出状态转移方程:由于路径只允许向右或者向下,所以 当前格子的方案数=从上一格走来的方案数+从左一格走来的方案数字 即 dp[i][j]=dp[i-1][j]+dp[i][j-1] 当然这是需要考虑到边界条件的。
- 设定初始状态:第一格的方案 dp[0][0] 为 1 ,同时到达第一行和第一列每一行的方案数也都是为 1 的。
- 执行状态转移:见代码
- 返回结果:由于数组的下标是从 0 开始的,因此最终需要的返回的第 m 行 n 列的方案数应当是 dq[m-1][n-1] 。
2.力扣LCP 06. 拿硬币
原题链接
源码剖析
class Solution {
public:
int minCount(vector<int>& coins) {
int ans = 0;
for(int i = 0 ; i < coins.size() ; ++i) {
ans += (coins[i]+1)/2;
}
return ans;
}
};
不论一共有几个都可以直接用个数除以二然后向上取整。
3.力扣2278
原题链接
源码剖析
class Solution {
public:
int percentageLetter(string s, char letter) {
int i , len = s.size();
int ans = 0;
for(i = 0 ; i < len ; ++i){
if(s[i] == letter){
ans++;
}
}
return 100*ans/len;
}
};
注意变量要初始化。
4.力扣1018
原题链接
源码剖析
class Solution {
public:
vector<bool> prefixesDivBy5(vector<int>& nums) {
vector<bool> ans;
int i = 0;
int sum = 0;
int len = nums.size();
while(i < len) {
sum<<=1;
sum+=nums[i];
sum%=5;
i++;
ans.push_back(!sum);
}
return ans;
}
};
这里有一个小技巧, sum 在判断过程中不断的模除 5 就可以防止 sum 的值过大。
5.力扣剑指 Offer 10- I. 斐波那契数列
原题链接
源码剖析
class Solution {
public:
int fib(int n) {
int dp[101] = {0};
dp[1] = 1;
for(int i = 2;i<=n;++i){
dp[i] = (dp[i-1] + dp[i-2])%1000000007;
}
return dp[n];
}
};
这题如果直接使用递归是会超时的,可以使用动态规划来实现。
6.力扣509
原题链接
源码剖析
class Solution {
public:
int fib(int n) {
int dp[31] = {0};
dp[1] = 1;
for(int i = 2;i<=n;++i){
dp[i] = dp[i-1] + dp[i-2];
}
return dp[n];
}
};
同上。
7.力扣剑指 Offer 10- II. 青蛙跳台阶问题
原题链接
源码剖析
class Solution {
public:
int numWays(int n) {
int dp[101];
dp[0] = 1;
dp[1] = 1;
for(int i = 2;i<=n;++i){
dp[i] = (dp[i-1] + dp[i-2])%1000000007;
}
return dp[n];
}
};
同上,不过需要修改一下初始值。
8.力扣70
原题链接
源码剖析
class Solution {
int dp[46];
public:
int climbStairs(int n) {
dp[0] = 1;
dp[1] = 1;
for(int i = 2 ; i <= n ; ++i){
dp[i] = dp[i-1] + dp[i-2];
}
return dp[n];
}
};
同上。
9.力扣剑指 Offer II 088. 爬楼梯的最少成本
原题链接
源码剖析
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
int dp[1001];
dp[0] = 0;
dp[1] = 0;
int n = cost.size();
for(int i = 2 ; i <= n; ++i){
dp[i] = min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]);
}
return dp[n];
}
};
这题一定要理清楚初始状态,然后到达当前层数的可能性就只有两种了,要不然就是爬了一格到当前层,要不然就是爬两层到当前层,然后取这两者中最少的就是到达当前楼层的最少花费。是一个最基础的动态规划。
10.力扣746
原题链接
源码剖析
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
int dp[1001];
dp[0] = 0;
dp[1] = 0;
int n = cost.size();
for(int i = 2 ; i <= n; ++i){
dp[i] = min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]);
}
return dp[n];
}
};
同上。
本文概述了如何使用动态规划解决力扣平台上的九道经典题目,包括路径计数、硬币取法、字符百分比、二进制前缀、斐波那契数列及其变种、爬楼梯问题、成本最小化和最优化策略。通过实例解析展示了每题的状态转移、初始条件和求解过程。
608

被折叠的 条评论
为什么被折叠?



