LeetCode刷题day37|738.单调递增的数字、714. 买卖股票的最佳时机含手续费、968.监控二叉树

文章目录

  • 一、738.单调递增的数字
  • 二、714. 买卖股票的最佳时机含手续费
  • 三、968.监控二叉树

一、738.单调递增的数字

注意的点:

  1. 将题目给出的数的每一位从右向左遍历,因为左边的依赖右边的,所以先更新右边的。
  2. 记录一个更新为9的最左边的位数,因为若某一位更新为9,则它右边所有数都要更新为9。

以下是代码部分:

//题解方法:从后向前遍历。若当前位比前一位小,则当前位赋9,前一位--
    public int monotoneIncreasingDigits2(int n) {

        if(n==0)
            return 0;

        //踩坑:没有定义临时变量,n的值在第一个循环中已经变0了
        int tmp = n;

        //先计算n的长度。
        int size = 0;
        while ( tmp!= 0){
            tmp /= 10;
            size++;
        }

        //定义数组,顺序从个位开始(反着的)
        int[] num = new int[size];
        for (int i = 0; i < num.length; i++) {
            num[i] = n%10;
            n /= 10;
        }

        //踩坑:记录9出现的最大位,比他小的位都可以放9
        int flag = -1;

        //数组从前向后遍历(即原数从后向前遍历
        for (int i = 1; i < num.length; i++) {

            //如果当前数大于前一个,
            if(num[i] > num[i-1]){
                //num[i-1] = 9;
                num[i]--;
                flag = i-1;
            }

        }

        int res;
        if( flag >= 0)
            res = 9;
        else
            res = num[0];
        for (int i = 1; i < num.length; i++) {
            if(flag >= i)
            //踩坑,这里是10的i次,而不是10*i
                res += 9*Math.pow(10, i);
            else
                res += num[i]*Math.pow(10, i);
        }

        return res;
    }

二、714. 买卖股票的最佳时机含手续费

需要注意的点:

  1. 需要一个minPrice变量记录当前一个区域内的最小买入价。
  2. 分三种情况:低于买入价(更新最低价)、高于买入价但无法回本(不做操作)、可以回本(尝试性买入)。
  3. 所谓尝试性买入,是指当前时刻会买入,但发现有更优解,则不在当天买入,退还手续费。所以,在更新minPrice时,会多一个 -fee 的动作。

以下是代码部分:

public class 买卖股票的最佳时机含手续费714 {

    //错误思想: 其实思路与不含手续费的 类似,都是只要有利可取(贪心)就买(唯一的不同是,因为含手续费所以不能每天都买(不能以两天为一个单位考虑),而是以几天为一个单位,当某一天能回本,就直接卖出)
    //还是不能看到利益就卖出,数量多了手续费也就多了,不划算了
    public int maxProfit(int[] prices, int fee) {

        int res = 0;
        //记录当前几天(当前一组中)最低的买入价
        int minPrice = prices[0];

        for (int i = 1; i < prices.length; i++) {

            //如果当前价格低于记录的最低价,则更新最低价
            if( minPrice > prices[i])
                minPrice = prices[i];

            //如果当前价格高于最低价,但是并没有回本。则不进行任何操作
            if( prices[i] > minPrice && prices[i] < minPrice + fee)
                continue;

            //就剩prices[i]可以回本的情况
            res += prices[i] - fee - minPrice;
            // 这里 -fee,是因为可能不需要在当前天卖出,后边还可以盈利。但是在上一行代码中已经减了fee,所以这里也要拉低买入的价格。如果不在当前天卖出则相互抵消,不用这一天出手续费
            minPrice = prices[i] - fee;
        }

        return res;
    }
}

三、968.监控二叉树

需要注意的点:

  1. 因为要求相机数量最少,所以要从根节点往上进行处理。
  2. 孩子节点分为三大类:孩子节点都被覆盖(当前节点可摆烂,让父节点操作),孩子节点有任意一个没被监控(当前节点不能摆烂,必须安一个相机),剩余其他情况(当前节点被覆盖了)
  3. 最后记得判断根节点的情况。

以下是代码部分:

public class 监控二叉树968 {

    int res = 0;

    public int minCameraCover(TreeNode root) {

        if(root == null)
            return 0;

        if(minCame(root) == 0)
            res++;

        return res;
    }

    private int minCame(TreeNode node){

        //空节点
        if( node == null )
            return 2;

        int left = minCame(node.left);
        int right = minCame(node.right);

        //三种情况  无覆盖0  有相机1  无相机有覆盖2
        //若其中某个孩子没被覆盖,就不能摆烂,自己要装相机
        if( left == 0 || right ==0){
            res++;
            return 1;
        }
        //这一步一定要在上一个判断的后边,否则会出错。
        if( left == 1 || right == 1)
            return 2;
        //注意这里是 && 只有当两个节点都被覆盖,才能摆烂,给自己的父节点
        if( left == 2 && right == 2)
            return 0;

        //不会走到这一步,只是让上边的三个分支描述清晰
        return -1;
    }
}

你可能感兴趣的:(leetcode,算法,职场和发展)