0
点赞
收藏
分享

微信扫一扫

算法练习-day30

f12b11374cba 2023-07-25 阅读 71

贪心算法

738. 单调递增的数字

题意:当且仅当每个相邻位数上的数字 x 和 y 满足 x <= y 时,我们称这个整数是单调递增的。给定一个整数 n ,返回 小于或等于 n 的最大数字,且数字呈 单调递增 。

实例:

算法练习-day30_贪心算法

思路:本题我最开始的思路是暴力求解:将数字倒序判断,如果该元素满足单调递增,则直接输出,很明显这个代码超时了;其次就是贪心算法:我们将数字转化为字符串,然后对其进行倒叙的判断,如果前一个元素大于后一个元素,我们就需要将前一个元素--,后一个元素变为9,这里我们用标记代替,如果这个元素不满足条件,就给一个标记,表示这个元素和后面的元素都需要设置为9

暴力求解代码:

bool IncreasNum(int n)
{
	vector<int> arr;
	while (n)
	{
		arr.push_back(n % 10);
		n /= 10;
	}
	for (int i = 1; i<arr.size(); i++)
	{
		if (arr[i - 1]<arr[i])
		{
			return false;
		}
	}
	return true;
}
int monotoneIncreasingDigits(int n) {
	for (int i = n; i>=0; i--)
	{
		if (IncreasNum(i))
		{
			return i;
		}
	}
	return 0;
}

贪心算法代码:

    int monotoneIncreasingDigits(int n) {
        string s=to_string(n);//数字变字符串
        int signal=INT_MAX;//先将标记放在最外侧,等待改变
        for(int i=s.size()-1;i>0;i--)
        {
            if(s[i-1]>s[i])//如果前一个元素大于后一个元素,不符合条件,此时后一个元素应该置9,前一个元素--
            {
                signal=i;
                s[i-1]--;
            }
        }
        for(int i=signal;i<s.size();i++)//如果我们的标记在字符串范围内,就说明字符串内有需要变为9的元素
        {
            s[i]='9';
        }
        return stoi(s);//字符串变数字
    }

968. 监控二叉树

题意:给定一个二叉树,我们在树的节点上安装摄像头。

节点上的每个摄影头都可以监视其父对象、自身及其直接子对象。

计算监控树的所有节点所需的最小摄像头数量。

实例:

算法练习-day30_贪心算法_02

思路:本题我在3月份的时候做过,对于解题的大致思路还是有印象的。为了实现监控的最小个数,举一个简单的例子:叶子节点大部分都是成对存在的,所以我们只需要将父节点作为监控节点可以覆盖叶子节点。因此我们需要从下往上进行监控的计算。

这里我们对节点有三种状态表示:0——表示该节点没有监控覆盖,1——表示该节点是监控节点,自身也被覆盖,2——表示该节点有监控覆盖。三种节点表达方式。

后序遍历中,当检测到节点为空时,我们默认其被覆盖返回2。

其次是后序遍历的遍历思想,左节点接受的是该节点对应的数字表达状态

最后是逻辑代码,这里也是有顺序的,大体分为三种情况:

  1. 当左右节点都被覆盖是,即都为2的情况。这里我们注意:这两个节点只是被覆盖,并不是监控节点。此时的父节点就应该是没有被覆盖的情况,所以返回0。
  2. 当左右节点的任意节点没有被覆盖时,由于我们是从下往上遍历的,因此就说明之前的监控节点都没有覆盖该节点。因此为了能覆盖该节点,我们就需要将父节点设置为监控节点,此时返回1。
  3. 当左右节点的任意节点被设置为监控节点时,那么它们的父节点必定是被覆盖的状态,此时返回2

最后就是在遍历完所有节点后,我们的根节点还需要进行最后一次判断。如果根节点是无覆盖状态,那么我们需要再次加入一个监控,就当是单独监控根节点了

C++代码:

    int count=0;
    int MonitorTree(TreeNode* root)//0——表示无覆盖,1——表示该节点有监控,2——表示有覆盖
    {
        if(nullptr==root)//当节点为空,我们默认为其已经被覆盖
        {
            return 2;
        }
        int left=MonitorTree(root->left);//后序遍历思想,从下往上遍历
        int right=MonitorTree(root->right);
        if(left==2&&right==2)//左右孩子都被覆盖,那么为了监控个数最小化,父节点不会被装监控
        {
            return 0;
        }
        if(left==0||right==0)//这里只要子节点有任何一个没有被覆盖,都需要我们的父节点成为1,去覆盖这个节点
        {
            count++;
            return 1;
        }
        if(left==1||right==1)//孩子为1,那么自身必须被覆盖
        {
            return 2;
        }
        return -1;
    }
    int minCameraCover(TreeNode* root) {
        if(MonitorTree(root)==0)//这里需要对根节点再次尽心判断,如果0,表示没有覆盖,那也是需要对其进行单独覆盖的
        {
            count++;
        }
        return count;
    }

举报

相关推荐

0 条评论