738.单调递增的数字
题目链接:Loading Question... - 力扣(LeetCode)
解题思路:
先将数字转换成字符串再转换成char数组,然后再进行处理,最后将char数组在转换回数字
创建一个samestart用于存储出现相等连续数字的时候的变更位置
没出现重复数字的情况下直接使用便利的下标i即可。
class Solution {
public int monotoneIncreasingDigits(int n) {
if(n >=0 && n <= 9) return n;
//432 399 452 449 410 399
// 思路:找到第一个不符合条件的数字,将他本身以及后面的所有数字变为9,前一位数字减1
char[] record = Integer.toString(n).toCharArray();
int j = -1;
int samestart = -1; // 用于记录连续重复数字中的第一个下标
for(int i = 1; i < record.length; i++){
if(record[i] == record[i - 1] && samestart == -1){ // 有重复的记录第一个
samestart = i;
}
else if(record[i] < record[i - 1]){
if(samestart == -1){
j = i;
record[j - 1]--;
}else{
j = samestart;
record[j - 1]--;
}
break;
}
else if(record[i] > record[i - 1]){
samestart = -1;
}
}
if(j == -1) return n;
for(int i = j; i < record.length; i++){
record[i] = '9';
}
System.out.println(Integer.valueOf(new String(record)));
return Integer.valueOf(new String(record));
}
}
714.买卖股票的最佳时机含手续费
题目链接:Loading Question... - 力扣(LeetCode)
解题思路:
其实最重要的一个点就是如何处理好手续费的问题,当股票一直涨或者下跌没超过手续费的时候,不会将股票频繁卖出,肯定是等股票涨不动了才卖。这种时候可以通过提前在minPrice中扣减手续费fee的方式来模拟一个中间交易过程没有手续费的情况。也就是说在股票一直涨的时候中间可以一直结算利润,不过不扣除手续费,只有在最后一次真正卖出这个股票完成交易的时候才扣除手续费。
class Solution {
public int maxProfit(int[] prices, int fee) {
int sum = 0;
// 遍历这个数组,维护一个startPrice
int minPrice = prices[0];
for(int i = 1; i < prices.length; i++){
// 在这里买入
if(minPrice > prices[i]) minPrice = prices[i];
// 什么也不做,在这里卖出入不敷出,有手续费,不买入不卖出
if(minPrice <= prices[i] && prices[i] <= minPrice + fee){
continue;
}
// 卖出!但是这里的卖出是一个相对含义,并非一定真正的卖出了,还要看后面这个股票会不会继续涨
if(prices[i] > minPrice + fee){
sum += prices[i] - minPrice - fee;
// 这里对minPrice进行一个手续费的扣减,在股票一直涨的情况下模拟没有手续费的买卖场景。
minPrice = prices[i] - fee; // 只有最后的最大值卖出点不使用这个minPrice,在最后才扣除这个手续费。
}
}
return sum;
}
}
968.监控二叉树
题目链接:968. 监控二叉树 - 力扣(LeetCode)
解题思路:
这个题需要思考的点:
二叉树的遍历方式,为什么要自底向上进行遍历:因为根据贪心算法,叶子节点肯定不要装摄像头。所以要自底向上,先考虑叶子节点
如何能够实现隔一个一个摄像头:采用状态转移的方式,标记每个结点的状态,根据状态计算摄像头个数
为什么要单独考虑最后的跟节点:因为根节点可能存在左孩子和右孩子都被覆盖的情况。这种情况在其他节点上面都只会直接标记一个未覆盖,并让未覆盖的父节点装摄像头,但是根节点没有父节点了,所以需要单独考虑。
class Solution {
int ans = 0;
public int minCame(TreeNode root){
if(root == null) return 2;
int left = minCame(root.left);
int right = minCame(root.right);
if(left == 2 && right == 2) return 0; // 左右都有覆盖,当前root一定无覆盖
if(left == 0 || right == 0){
ans++; // root需要安装摄像头 数量加1
return 1; // 返回安装摄像头状态
}
else return 2;
}
public int minCameraCover(TreeNode root) {
// 递归的方法解题
if(minCame(root) == 0){
ans++;
}
return ans;
}
}