62. Unique Paths
class Solution {
public:
int uniquePaths(int m, int n) {
vector<vector<int>> dp(m, vector<int>(n, 0));
for(int i=0; i<m; i++){
dp[i][0] = 1;
}
for(int j=0; j<n; j++){
dp[0][j] = 1;
}
for(int i=1; i<m; i++){
for(int 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] 是什么意思
63. Unique Paths II
lass Solution {
public:
int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
int m = obstacleGrid.size();
int n = obstacleGrid[0].size();
if(obstacleGrid[0][0] == 1 || obstacleGrid[m-1][n-1] == 1) return 0;
vector<vector<int>> dp(m, vector<int>(n,0));
for(int i=0; i<m; i++){
if(obstacleGrid[i][0] != 1){
dp[i][0] = 1;
}else{
break;
}
}
for(int j=0; j<n; j++){
if(obstacleGrid[0][j] != 1){
dp[0][j] = 1;
}else{
break;
}
}
for(int i=1; i<m; i++){
for(int j=1; j<n;j++){
if(obstacleGrid[i][j] != 1){
dp[i][j] = dp[i-1][j] + dp[i][j-1];
}
}
}
return dp[m-1][n-1];
}
};
注意:
1.注意特殊的情况开头和结尾是1的
2.在设置初始值的时候,如果其中一个为1,那么后面的就都是0了
错误代码:
for(int i=0; i<m; i++){
if(obstacleGrid[i][0] != 1){
dp[i][0] = 1;
}
}
可以在上面代码的基础上在做一点改进
for(int i=0; i<m && obstacleGrid[i][0] == 0; i++){
dp[i][0] = 1;
}
这样写更简洁一点
343. Integer Break
class Solution {
public:
int integerBreak(int n) {
vector<int> dp(n+1, 0);
dp[2] = 1;
for(int i=3; i<=n; i++){
for(int j=1; j<i-1; j++){
dp[i] = max(dp[i], max(j*(i-j), j*dp[i-j]));
}
}
return dp[n];
}
};
1.这里的dp[i] 指的是 整数i拆分出来的最大乘积
2.一开始没有想清楚递推公式
96. Unique Binary Search Trees
class Solution {
public:
int numTrees(int n) {
vector<int> dp(n+1, 0);
dp[0] = 1;
dp[1] = 1;
for(int i=2; i<=n; i++){
for(int j=0;j<i;j++){
dp[i] += dp[j]*dp[i-j-1];
}
}
return dp[n];
}
};
从左右子树出发开始找规律
416. Partition Equal Subset Sum (还是有点懵)
class Solution {
public:
bool canPartition(vector<int>& nums) {
int sum=0;
for(int num:nums){
sum += num;
}
if(sum%2 == 1) return false;
vector<int> dp(sum/2+1, 0);
for(int i=0; i<nums.size(); i++){
for(int j=sum/2; j>=nums[i]; j--){
dp[j] = max(dp[j], dp[j-nums[i]]+nums[i]);
}
}
if(dp[sum/2] == sum/2) return true;
return false;
}
};
想法是找到sum/2
1049. Last Stone Weight II
class Solution {
public:
int lastStoneWeightII(vector<int>& stones) {
int sum=0;
for(int stone:stones){
sum += stone;
}
vector<int> dp(sum/2+1, 0);
for(int i=0; i<stones.size();i++){
for(int j = sum/2; j>=stones[i]; j--){
dp[j] = max(dp[j], dp[j-stones[i]]+stones[i]);
}
}
return sum-dp[sum/2]-dp[sum/2];
}
};
跟上一道题很像,其实就是找最相近的两个和的差
494. Target Sum
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int target) {
int sum=0;
for(int num:nums){
sum += num;
}
if(abs(target) > sum || (target+sum)%2 == 1) return 0;
int val = (sum+target)/2;
vector<int> dp(val+1,0);
dp[0]=1;
for(int i=0; i<nums.size(); i++){
for(int j=val; j>=nums[i]; j--){
dp[j] += dp[j-nums[i]];
}
}
return dp[val];
}
};
1.求组合数的递推公式很多都是 dp[j] += dp[j-nums[i]]
2.注意两个特殊情况
3.这里的dp[0]是1了,不再是0了
文章讲述了几个编程问题,涉及动态规划方法解决的独特路径计数、带有障碍物的路径、整数分解、二叉搜索树数量、等和子集划分和石头重量问题。这些问题的核心是使用状态转移方程来求解最优化问题。
5704

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



