● 738.单调递增的数字
● 968.监控二叉树
● 总结
1.单调递增的数字
关联 leetcode 738.单调递增的数字
-
思路
- 从前往后遍历
- 可能导致数字结果变化
- 从后往前遍历
- 保持后面已经处理的结果,前面跟着更新
- 不存在数字变化
- 保持后面已经处理的结果,前面跟着更新
- 从前往后遍历
-
题解
func monotoneIncreasingDigits(n int) int { if n < 10 { return n } str := strconv.Itoa(n) nStr := []byte(str) //Go字符串不能修改,需要类型转换为数组 flag := len(nStr) //从当前位往后全部标记为9 for i := len(nStr) - 1; i > 0; i-- { //后一位小于前一位, 不满足递增 if nStr[i-1] > nStr[i] { nStr[i-1]-- flag = i } } for i := flag; i < len(nStr); i++ { nStr[i] = '9' } res, _ := strconv.Atoi(string(nStr)) return res }
2.监控二叉树 (可以跳过)
关联 leetcode 968.监控二叉树 (可以跳过)
本题是贪心和二叉树的一个结合,比较难,一刷大家就跳过吧。
https://programmercarl.com/0968.监控二叉树.html
- 思路
- 从下往上看
- 摄像头从叶子层上一层开始放置
- 省下 叶子/2 个摄像头
- 局部最优 —》全局最优
- 大体思路就是从低到上,先给叶子节点父节点放个摄像头,然后隔两个节点放一个摄像头,直至到二叉树头结点
- 摄像头从叶子层上一层开始放置
- 二叉树遍历顺序
- 从下往上推:后序遍历 左右中
- 隔两个节点放一个摄像头
- 节点可能有的状态
- 0:节点无覆盖
- 1:节点有摄像头
- 2:节点有覆盖
- 空节点的处理:
- 补足成一个虚拟叶子,虚拟成 有覆盖的状态
- 节点可能有的状态
- 单层逻辑处理
- 情况1:左右节点都有覆盖
- 左孩子有覆盖,右孩子有覆盖,那么此时中间节点应该就是无覆盖的状态了。
- 情况2:左右节点至少有一个无覆盖的情况
- 如果是以下情况,则中间节点(父节点)应该放摄像头
- left == 0 && right == 0 左右节点无覆盖
- left == 1 && right == 0 左节点有摄像头,右节点无覆盖
- left == 0 && right == 1 左节点有无覆盖,右节点摄像头
- left == 0 && right == 2 左节点无覆盖,右节点覆盖
- left == 2 && right == 0 左节点覆盖,右节点无覆盖
- 如果是以下情况,则中间节点(父节点)应该放摄像头
- 情况3:左右节点至少有一个有摄像头
- 如果是以下情况,其实就是 左右孩子节点有一个有摄像头了,那么其父节点就应该是2(覆盖的状态)
- left == 1 && right == 2 左节点有摄像头,右节点有覆盖
- left == 2 && right == 1 左节点有覆盖,右节点有摄像头
- left == 1 && right == 1 左右节点都有摄像头
- 如果是以下情况,其实就是 左右孩子节点有一个有摄像头了,那么其父节点就应该是2(覆盖的状态)
- 情况4:头结点没有覆盖
- 还要判断根节点,如果没有覆盖,摄像头+1
- 情况1:左右节点都有覆盖
- 从下往上看
- 题解
- 插个眼二刷来补全
总结
- 没有框架没有套路
- 思路重在巧妙
- 找不出反例就胜利了
- 多练多见
- 能找到局部最优
- 累计优势 —》全局最优
- 就是岩心
- 累计优势 —》全局最优
- 多维度问题
- 一次解决一个维度
- 不要贪