算法训练营day37_贪心算法(3.9)

算法训练营day37_贪心算法(3.9)

738.单调递增的数字

首先暴力肯定是超时的,A不了;

首先特判一下是不是全都是一样的数,直接输出原数;(因为后面的逻辑是判断当前数跟下一个数,怕影响,就先特判了)

可以转变为字符串,从高位往低位走;

  • 如果当前位>下一位,当前位-1,之后的位都是9;
  • 如果当前位=下一位,还要判断一串相等的数后面的数大还是小,如果小,那么当前位-1,之后的位都是9,如果大,那么不操作;
  • 否则就直接取数,不操作;
class Solution {
public:
    int monotoneIncreasingDigits(int n) {
        string t=to_string(n);
        int ans=0;
        int len=t.size();

        bool flag=true;
        for(int i=1;i<len;i++){
            if(t[i]!=t[0]){
                flag=false;
                break;
            } 
        }
        if(flag) return n;

        for(int i=0;i<len;i++){
            if(i!=len-1&&t[i]>t[i+1]){
                ans=ans*10+t[i]-'0'-1;
                for(int cnt=0;cnt<len-1-i;cnt++){
                    ans=ans*10+9;
                }
                break;
            }
            if(i!=len-1&&t[i]==t[i+1]){
                int j=i+1;
                while(j<len&&t[j]==t[i]) j++;
                if(t[j]>t[i]){
                    ans=ans*10+t[i]-'0';
                    continue;
                };
                ans=ans*10+t[i]-'0'-1;
                for(int cnt=0;cnt<len-1-i;cnt++){
                    ans=ans*10+9;
                }
                break;
            }
            ans=ans*10+t[i]-'0';
        }
        return ans;
    }
};

随想录思路:

若当前>下一位,当前-1,下一位变为9;(有可能后面一串相等的,这些也要变,所以记录一下变9的后面都要变9);

倒序遍历,可以保证后面迭代的结果可以用在前面;(倒序遍历很关键)

class Solution {
public:
    int monotoneIncreasingDigits(int n) {
        string t=to_string(n);
        int len=t.size();
        int flag=len;
        for(int i=len-1;i>=1;i--){
            if(t[i-1]>t[i]){
                flag=i;
                t[i-1]--;
            }
        }
        for(int i=flag;i<len;i++){
            t[i]='9';
        }

        int ans=stoi(t);
        return ans;
    }
};

968. 监控二叉树

这道题挺难的,周赛2124分的题;

我的思路wa了,只过了一半(正确思路wa了之后看出来了,不知道咋实现,还想着单节点操作下面两层。。。没实现);

我的(错误)思路

叶子节点的父亲必装;

只要儿子都装了,自己就不用装;

有一个没装,自己就要装;

//wa一半代码
class Solution {
public:
    int ans;

    bool dfs(TreeNode* u){
        if(u->left==NULL&&u->right==NULL) return false;
        if(u->left!=NULL&&u->right==NULL){
            if(dfs(u->left)) return false;
        }
        if(u->left==NULL&&u->right!=NULL){
            if(dfs(u->right)) return false;
        }
        if(u->left!=NULL&&u->right!=NULL){
            bool flag1=dfs(u->left);
            bool flag2=dfs(u->right);
            if(flag1&&flag2) return false;
        }
        ans++;
        return true;
    }

    int minCameraCover(TreeNode* root) {
        ans=0;
        if(root->left==NULL&&root->right==NULL) return 1;
        dfs(root);
        return ans;
    }
};

正确思路:

尽量让每个灯都处于中间的位置(可辐射到父亲,孩子),叶子结点的父亲要装;

考虑节点的状态,三个,0未覆盖,1放摄像头,2没放摄像头但被覆盖;

  1. 如果存在孩子为未覆盖0,则返回1放摄像头;
  2. 如果存在孩子为摄像头1,则返回2没放但被覆盖;
  3. 如果孩子都是2没放摄像头但被覆盖,则返回0未覆盖(开启新的”叶子节点“,让自己父亲放);

因此,为了让叶子节点的父亲放,空结点返回2,让叶子节点为1;

还要考虑最后的根节点,根节点也会返回值,如果为0代表未被覆盖,需要放;如果为1,2说明被覆盖了;

class Solution {
public:
    int ans;

    int dfs(TreeNode* u){
        if(u==NULL) return 2;
        int flag1=dfs(u->left);
        int flag2=dfs(u->right);
        if(flag1==0||flag2==0){
            ans++;
            return 1;
        }
        if(flag1==1||flag2==1) return 2;
        return 0;
    }

    int minCameraCover(TreeNode* root) {
        ans=0;
        if(dfs(root)==0) ans++;
        return ans;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值