算法记录 | Day37 贪心算法

这篇具有很好参考价值的文章主要介绍了算法记录 | Day37 贪心算法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

738.单调递增的数字

思路:

1.一旦出现strNum[i - 1] > strNum[i]的情况(非单调递增),首先想让strNum[i - 1]–,然后strNum[i]给为9,这样这个整数就是89,即小于98的最大的单调递增整数。

2.向后遍历

从前向后遍历的话,遇到strNum[i - 1] > strNum[i]的情况,让strNum[i - 1]减一,但此时如果strNum[i - 1]减一了,可能又小于strNum[i - 2]。

e.g:332,从前向后遍历的话,那么就把变成了329,此时2又小于了第一位的3了,真正的结果应该是299。

​ 后向前遍历332的数值变化为:332 -> 329 -> 299

class Solution:
    def monotoneIncreasingDigits(self, n: int) -> int:
        a = list(str(n))
        for i in range(len(a)-1,0,-1):
            if int(a[i]) < int(a[i-1]):
                a[i-1] = str(int(a[i-1])-1)
                a[i:] = '9' *(len(a)-i)
        return int("".join(a))

968.监控二叉树

思路:

让叶子节点的父节点安摄像头,所用摄像头最少,整体最优:全部摄像头数量所用最少!

可以使用后序遍历的方式遍历二叉树的节点,这样就可以优先遍历叶子节点。

对于每个节点,利用贪心思想,可以确定三种状态:

  • 第一种状态:该节点无覆盖
  • 第二种状态:该节点已经装上了摄像头
  • 第三种状态:该节点已经覆盖

为了让摄像头数量最少,要尽量让叶子节点的父节点安装摄像头,这样才能摄像头的数量最少。对此应当分析当前节点和左右两侧子节点的覆盖情况。

  • 情况1:左右节点都有覆盖

​ 左孩子有覆盖,右孩子有覆盖,那么此时中间节点应该就是无覆盖的状态了。

if left == 2 and right == 2:
   return 0

算法记录 | Day37 贪心算法

  • 情况2:左右节点至少有一个无覆盖的情况,如果是以下情况,则中间节点(父节点)应该放摄像头:

    • left == 0 && right == 0 左右节点无覆盖

    • left == 1 && right == 0 左节点有摄像头,右节点无覆盖

    • left == 0 && right == 1 左节点有无覆盖,右节点摄像头

    • left == 0 && right == 2 左节点无覆盖,右节点覆盖

    • left == 2 && right == 0 左节点覆盖,右节点无覆盖

这个不难理解,毕竟有一个孩子没有覆盖,父节点就应该放摄像头。

此时摄像头的数量要加一,并且return 1,代表中间节点放摄像头。

# Case 2:
    # left == 0 && right == 0 左右节点无覆盖
    # left == 1 && right == 0 左节点有摄像头,右节点无覆盖
    # left == 0 && right == 1 左节点有无覆盖,右节点摄像头
    # left == 0 && right == 2 左节点无覆盖,右节点覆盖
    # left == 2 && right == 0 左节点覆盖,右节点无覆盖
if left == 0 or right == 0:
	result += 1
return 1
  • 情况3:左右节点至少有一个有摄像头,如果是以下情况,其实就是 左右孩子节点有一个有摄像头了,那么其父节点就应该是2(覆盖的状态)

    • left == 1 && right == 2 左节点有摄像头,右节点有覆盖

    • left == 2 && right == 1 左节点有覆盖,右节点有摄像头

    • left == 1 && right == 1 左右节点都有摄像头

算法记录 | Day37 贪心算法

# Case 3:
    # left == 1 && right == 2 左节点有摄像头,右节点有覆盖
    # left == 2 && right == 1 左节点有覆盖,右节点有摄像头
    # left == 1 && right == 1 左右节点都有摄像头
if left == 1 or right == 1:
   return 2
  • 情况4:头结点没有覆盖,以上都处理完了,递归结束之后,可能头结点 还有一个无覆盖的情况,如图:

算法记录 | Day37 贪心算法文章来源地址https://www.toymoban.com/news/detail-420793.html

if traversal(root) == 0:
	result += 1
class Solution:
    def minCameraCover(self, root: TreeNode) -> int:
        # Greedy Algo:
        # 从下往上安装摄像头:跳过leaves这样安装数量最少,局部最优 -> 全局最优
        # 先给leaves的父节点安装,然后每隔两层节点安装一个摄像头,直到Head
        # 0: 该节点未覆盖
        # 1: 该节点有摄像头
        # 2: 该节点有覆盖

        result = 0
        # 从下往上遍历:后序(左右中)
        def traversal(curr: TreeNode) -> int:
            nonlocal result

            if not curr: return 2
            left = traversal(curr.left)
            right = traversal(curr.right)

            # Case 1:
            # 左右节点都有覆盖
            if left == 2 and right == 2:
                return 0

            # Case 2:
                # left == 0 && right == 0 左右节点无覆盖
                # left == 1 && right == 0 左节点有摄像头,右节点无覆盖
                # left == 0 && right == 1 左节点有无覆盖,右节点摄像头
                # left == 0 && right == 2 左节点无覆盖,右节点覆盖
                # left == 2 && right == 0 左节点覆盖,右节点无覆盖
            elif left == 0 or right == 0:
                result += 1
                return 1

            # Case 3:
                # left == 1 && right == 2 左节点有摄像头,右节点有覆盖
                # left == 2 && right == 1 左节点有覆盖,右节点有摄像头
                # left == 1 && right == 1 左右节点都有摄像头
            elif left == 1 or right == 1:
                return 2

            # 其他情况前段代码均已覆盖

        if traversal(root) == 0:
            result += 1

        return result

到了这里,关于算法记录 | Day37 贪心算法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 算法打卡day32|贪心算法篇06|Leetcode 738.单调递增的数字、968.监控二叉树

    Leetcode 738.单调递增的数字 题目链接:738.单调递增的数字  大佬视频讲解:单调递增的数字视频讲解  个人思路 这个题目就是从例子中找规律,例如 332,从后往前遍历,32不是单调递增将2变为9,3减1,变成了329,遍历到2,32不是递增,将2变为9,3减1,变成299,符合题目条件,打印

    2024年04月16日
    浏览(44)
  • 贪心算法part6 | ● 738.单调递增的数字 ● 968.监控二叉树

    代码随想录算法训练营第一天 | 题目、题目 738.单调递增的数字 局部最优:前一个数比当前数小,前一个数位减一,当前数置为9 题目要求小于等于N的最大单调递增的整数,那么拿一个两位的数字来举例。 例如:98,一旦出现strNum[i - 1] strNum[i]的情况(非单调递增),首先想

    2024年02月10日
    浏览(38)
  • 算法记录 | Day37 贪心算法

    思路: 1.一旦出现strNum[i - 1] strNum[i]的情况(非单调递增),首先想让strNum[i - 1]–,然后strNum[i]给为9,这样这个整数就是89,即小于98的最大的单调递增整数。 2.向后遍历 从前向后遍历的话,遇到strNum[i - 1] strNum[i]的情况,让strNum[i - 1]减一,但此时如果strNum[i - 1]减一了,可能

    2023年04月22日
    浏览(30)
  • 力扣第738题 单调递增的数字 c++ 暴力超时 贪心优化

    738. 单调递增的数字 中等 相关标签 贪心  数学 当且仅当每个相邻位数上的数字  x  和  y  满足  x = y  时,我们称这个整数是 单调递增 的。 给定一个整数  n  ,返回  小于或等于  n  的最大数字,且数字呈  单调递增  。 示例 1: 示例 2: 示例 3: 提示: 0 = n = 109 从N开始

    2024年02月08日
    浏览(37)
  • 贪心算法学习——最长单调递增子序列

    目录 ​编辑 一,题目 二,题目接口 三,解题思路和代码 给你一个整数数组  nums  ,找到其中最长严格递增子序列的长度。 子序列  是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如, [3,6,2,7]  是数组  [0,3,1,6,2,2,7]  的子序列。  

    2024年02月08日
    浏览(40)
  • Day 37 贪心算法 6

    代码随想录  1. 思路 从后向前判断,如果不呈现单调递增的状态,后一位变成9,前一位-1。这里局部最优是每两位的最优解,从后向前线性遍历能得到全局最优。 但是有一点没有想清楚 。如果出现了上述的两位数倒序情况,之后的所有数字都应该变成9。例如52583,最小的递

    2024年02月01日
    浏览(37)
  • Day37 贪心算法part06

    前面都想到了,结果最后n[i]给写错了直接写成9了,得把后面的全都改成9才行 摄像头的覆盖范围是上中下 遇到叶子结点,放到叶子结点的父节点 每隔两个空节点放一个摄像头 所以要用后序遍历 把结点分为三个状态:0无覆盖1有摄像头2有覆盖 空节点要设置为有覆盖的状态

    2024年02月19日
    浏览(45)
  • DAY37:贪心算法(四)跳跃游戏+跳跃游戏Ⅱ

    给定一个非负整数数组 nums ,你最初位于数组的 第一个下标 。 数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标。 示例 1: 示例 2: 提示: 1 = nums.length = 3 * 104 0 = nums[i] = 105 思路 游戏大致规则如下图。每一步代表着能跳跃的最大长

    2024年02月12日
    浏览(42)
  • 单调递增的数字——力扣738

    题目描述 解法

    2024年02月13日
    浏览(35)
  • 【Leetcode】 738. 单调递增的数字

    当且仅当每个相邻位数上的数字 x 和 y 满足 x = y 时,我们称这个整数是 单调递增 的。 给定一个整数 n ,返回 小于或等于 n 的最大数字,且数字呈 单调递增 。 示例 1 : 输入 : n = 10 输出 : 9 示例 2 : 输入 : n = 1234 输出 : 1234 示例3 : 输入 : n = 332 输出 : 299 提示: AC : 需要注意的点

    2024年02月07日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包