代码随想录day37 贪心算法
题738 单调递增的数字
需要明确三点
1,遍历顺序,从后往前。因为如果从前往后遍历过的数字可能又会被更改。
2,当前数字如果比后一个数字小,那么要将当前数字减1,后一个数字变成9.
3,需要从后往前记录最后一个(就是最高位)需要变成9的位置,并且将其后面的数字全部变成9。所以需要做两个循环。
class Solution {
public int monotoneIncreasingDigits(int n) {
String s = String.valueOf(n);
char[] chars = s.toCharArray();
int start = s.length();//用来记录需要成9的位置,这个位置之后所有的数字都要变为9
for(int i = s.length() - 2; i >= 0; i--) {
if(chars[i] > chars[i + 1]){
chars[i]--;
start = i + 1;
}
}
for(int i = start; i < s.length(); i++) {
chars[i] ='9';
}
return Integer.parseInt(String.valueOf(chars));
}
}
题714 买卖股票的最佳时机含手续费
1,记录最底买入价的时候把手续费带上。
2,对于卖出日期,其实并不需要确切地知道哪一天,而是当有利可图的时候(卖出价大于买入加手续费)就计算利润,连续收获利润的最后一天就是具体的卖出日。
3,计算利润之后需要将买入价更新为当前的股票价格(不需要包含手续费),因为并不是真正的要卖出,切手续费已经包含在第一次买入价中了,真正卖出的时候只需要计算一次手续费。
class Solution {
public int maxProfit(int[] prices, int fee) {
int buy = prices[0] + fee;
int sum = 0;
for (int p : prices) {
//更新买入
if(p + fee < buy) {
buy = p + fee;
} else if (p > buy) {
//当前价格比买入价加上手续费还要大,可以计算利润
sum += p - buy;
buy = p;//这一步很关键,相当于并不是真正的买入,只有最后一次计算才是真正意义上的卖出
}
}
return sum;
}
}
题968 监控二叉树
1,挺难的一道题,首先需要弄清楚遍历顺序,后序遍历
2,要得到最小的摄像头的个数,那么摄像头不能位于叶子节点上,应该在叶子节点的父节点放置摄像头,这样才能使整体摄像头数量最少。
3,将节点的状态分为3种,分别判断。
class Solution {
int result = 0;
public int minCameraCover(TreeNode root) {
if(minCamera(root) == 0){
result++;
}
return result;
}
/**
节点的状态值:0代表无覆盖,1代表有摄像头,2代表有覆盖。
后序遍历,根据左右节点的情况来判断自己的状态。
*/
public int minCamera(TreeNode root) {
if(root == null){
return 2; //避免在叶子节点上放摄像头
}
int left = minCamera(root.left);
int right = minCamera(root.right);
if(left == 2 && right == 2) {
return 0;
} else if(left == 0 || right == 0) {
result++; //左右有任何一个没有覆盖,则该节点上应该放一个摄像头。
return 1;
} else {
return 2;
}
}
}