738.单调递增的数字
方法一 暴力破解 (超时了)
class Solution {
private:
// 判断一个数字的各位上是否是递增
bool checkNum(int num) {
int max = 10;
while (num) {
int t = num % 10;
if (max >= t) max = t;
else return false;
num = num / 10;
}
return true;
}
public:
int monotoneIncreasingDigits(int N) {
for (int i = N; i > 0; i--) { // 从大到小遍历
if (checkNum(i)) return i;
}
return 0;
}
};
方法二 贪心算法
解题思路: 先判断给出的数字是不是单调递增的数字。如果是,直接输出。
如果不是,一旦出现strNum[i - 1] > strNum[i]
的情况(非单调递增),首先想让strNum[i - 1]--
,然后strNum[i]
给为9。考虑从后遍历还是从前遍历,如果从前遍历,可能会遇到strNum[i - 1] > strNum[i]
的情况,让strNum[i - 1]
减一,但此时如果strNum[i - 1]
减一了,可能又小于strNum[i - 2]
。
例如:332 寻找一个合适的单调递增数字,如果从前遍历可能会是329,不满足题意,真正满足的应该是299。
因此本题可以考虑从后遍历。
class Solution {
public:
int monotoneIncreasingDigits(int N) {
string strNum = to_string(N); //将整数N转换为字符串表示形式
// flag用来标记赋值9从哪里开始
// 设置为这个默认值,为了防止第二个for循环在flag没有被赋值的情况下执行
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 = flag; i < strNum.size(); i++) {
strNum[i] = '9';
}
return stoi(strNum); //stoi函数 作用是将 n 进制的字符串转化为十进制
}
};
714. 买卖股票的最佳时机含手续费
题目链接
**解题思路:**本题在122.买卖股票的最佳时机II基础上,又增加了手续费这一限制条件。
在做收获利润操作的时候其实有三种情况:
- 情况一:收获利润的这一天并不是收获利润区间里的最后一天(不是真正的卖出,相当于持有股票),所以后面要继续收获利润。
- 情况二:前一天是收获利润区间里的最后一天(相当于真正的卖出了),今天要重新记录最小价格了。
- 情况三:不作操作,保持原有状态(买入,卖出,不买不卖)
class Solution {
public:
int maxProfit(vector<int>& prices, int fee) {
int result = 0;
int minPrice = prices[0]; // 记录最低价格
for (int i = 1; i < prices.size(); i++) {
// 情况二:相当于买入
if (prices[i] < minPrice) minPrice = prices[i];
// 情况三:保持原有状态(因为此时买则不便宜,卖则亏本)
//if (prices[i] >= minPrice && prices[i] <= minPrice + fee) {
// continue;
}
// 计算利润,可能有多次计算利润,最后一次计算利润才是真正意义的卖出
if (prices[i] > minPrice + fee) {
result += prices[i] - minPrice - fee;
minPrice = prices[i] - fee; // 情况一,这一步很关键
}
}
return result;
}
};
968.监控二叉树
题目链接
解题思路: 从低到上,先给叶子节点父节点放个摄像头,然后隔两个节点放一个摄像头,直至到二叉树头结点。
此时这道题目还有两个难点:
- 二叉树的遍历
- 如何隔两个节点放一个摄像头
class Solution {
private:
int result;
int traversal(TreeNode* cur) {
if (cur == NULL) return 2;
int left = traversal(cur->left); // 左
int right = traversal(cur->right); // 右
if (left == 2 && right == 2) return 0;
else if (left == 0 || right == 0) {
result++;
return 1;
} else return 2;
}
public:
int minCameraCover(TreeNode* root) {
result = 0;
if (traversal(root) == 0) { // root 无覆盖
result++;
}
return result;
}
};