代码随想录训练营第37天|LeetCode 738.单调递增的数字、714. 买卖股票的最佳时机含手续费、 968.监控二叉树

参考

代码随想录

题目一:LeetCode 738.单调递增的数字

找规律:
100 —> 99
332 —> 299
98 —> 89
10 —> 9
得到的数都有一个特点,以9结尾,不难理解,这样才能保证这个数最大。
对于数字n,如果第i位比第i+1位大,那么应该将第i位减1,第i+1位变成9,这是局部的变化方法,而整体应该从后往前遍历,因为如果从前往后遍历,那么第i为减1之后就很可能导致比第i-1位还小(例如如果从前往后遍历,332得到的是329,显然不对),因此要从后往前遍历。代码实现如下:

class Solution {
public:
    int monotoneIncreasingDigits(int n) {
        string strNum = to_string(n);
        int index = strNum.size();
        for(int i = strNum.size()-1; i > 0; i--){
            if(strNum[i] < strNum[i-1]){
                index = i;
                strNum[i - 1] --;
            }
        }
        for(int i = index; i < strNum.size(); i++)
            strNum[i] = '9';
        return stoi(strNum);
    }
};

题目二:LeetCode 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;
    }
};

你可能感兴趣的:(代码随想录训练营,leetcode,算法)