引言
代码
第一题
这一题的思路就是我们从最后面开始向前遍历,找到第一个开始不符合单调递增的数字,然后把那个数据进行一个标记,同时-1,因为我们都知道,这个数后面的所有数都要变成9,因为可以保证递增的前提下数是最大的,但是如果这个数不-1,那么更新后的数一定比本数据要大。
cpp
class Solution {
public:
int monotoneIncreasingDigits(int n) {
string strNum = to_string(n);
int flag = strNum.size();
for (int i = strNum.size() - 1; i > 0; i--) {
if (strNum[i - 1] > strNum[i]) {
flag = i;
strNum[i - 1]--;
}
}
for (int i = 0; i < strNum.size(); i++) {
if (i >= flag) {
strNum[i] = '9';
}
}
return stoi(strNum);
}
};
动态规划的思路
第一步:确定dp数组的含义,比如dpi表示的是第i个的。。。。
第二步:确定递推公式
第三步:初始化dp数组
第四步:确定遍历顺序
第二题
这一题我们先要明白dp的含义是当有n个结点的时候有多少种情况。我们要讨论二叉搜索树的情况,主要就是根节点的不同,不同的根节点就代表把一颗树分成了什么样,然后子树又继续分,所以我们可以很容易的想到,我们需要轮流遍历每个根节点,然后假设第j个是根节点的时候,左边又j - 1个结点,右边有i - j个结点,所以根据dp的含义,就有了递推公式dpi += dpj - 1 * dpi - j
cpp
class Solution {
public:
int numTrees(int n) {
vector<int> dp(n + 1, 0); // n个结点的数量
dp[0] = 1;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
dp[i] += dp[j - 1] * dp[i - j];
}
}
return dp[n];
}
};
01背包
dpij的含义是我们处理从第一个物品到第i个物品,这个时候背包的承受量是j,此时最大的价值是多少。
二维数组
先遍历物品
cpp
// 先遍历物品
for (int i = 1; i < weight.size(); i++) {
for(int j = 0; j <= bagWeight.size(); j++) {
if (weight[i] > j) {
dp[i][j] = dp[i - 1][j];
} else {
dp[i][j] = max(dp[i][j - weight[i]] + value[i], dp[i - 1][j]);
}
}
}
先遍历背包容量
cpp
// weight数组的大小 就是物品个数
for(int j = 0; j <= bagweight; j++) { // 遍历背包容量
for(int i = 1; i < weight.size(); i++) { // 遍历物品
if (j < weight[i]) dp[i][j] = dp[i - 1][j];
else dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
}
}
一维数组
cpp
for(int i = 0; i < weight.size(); i++) { // 遍历物品
for(int j = bagWeight; j >= weight[i]; j--) { // 遍历背包容量
dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
}
}
第三题
这一题我们很难想到是用01背包来写的,我们用01背包来写的思路是因为数组的和可以分成两个部分,那么把和分成两半,target就是背包的容量。这里的dpj表示容量为j的背包最大价值是多少,因为这里重量和价值是一样的,所以我们只需要判断容量为target的时候价值最大是不是target,然后也不需要担心会不会有numsi比target还要大,因为我们有j >= numsi在兜底,可以保证我们每一次的背包都不会超重。
cpp
class Solution {
public:
bool canPartition(vector<int>& nums) {
int sum = 0;
for (int i = 0; i < nums.size(); i++) {
sum += nums[i];
}
if (sum % 2 != 0) {
return false;
}
int target = sum / 2;
vector<int> dp(1000000, 0);
for (int i = 0; i < nums.size(); i++) {
for (int j = target; j >= nums[i]; j--) {
dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]);
}
}
if (target == dp[target]) {
return true;
}
return false;
}
};
总结
本篇文章到这里就结束了!!!希望可以帮助大家理解~~~~