-
738单调递增的数字
- 代码随想录 (programmercarl.com)
-
第一印象
- 可以利用字符串转换获得数字的位数,然后根据位数的循环得到各个位的余数,然后分别讨论相邻数字的关系,再依靠位数次序构建答案。难点在于边界条件的建立。
-
讲解观后感
- 可以直接使用整数数组,这样就可以直接比较每个每个位置的数字了。
- 以98为例:一旦出现
strNum[i - 1] > strNum[i]的情况(非单调递增),首先想让strNum[i - 1]--,然后strNum[i]给为9,这样这个整数就是89,即小于98的最大的单调递增整数。 - 以从后向前的便利过程就可以通过局部最优推导出全局最优
-
解题代码
-
func monotoneIncreasingDigits(N int) int { s := strconv.Itoa(N)//将数字转为字符串,方便使用下标 ss := []byte(s)//将字符串转为byte数组,方便更改。 lenth := len(ss) if lenth <= 1 { return N } for i := lenth-1; i > 0; i-- { if ss[i-1] > ss[i] { //前一个大于后一位,前一位减1,后面的全部置为9 ss[i-1] -= 1 for j := i; j < lenth; j++ { //后面的全部置为9 ss[j] = '9' } } } res, _ := strconv.Atoi(string(ss)) return res } -
986监控二叉树
- 代码随想录 (programmercarl.com)
-
第一印象
- 自己画了一下树,监控节点监控子节点时可以监控两个节点,而只能向上监控一个节点,并且每向下一层,理论上的叶子节点就会增加,因此监控节点也许应尽量靠近根部。
-
讲解观后感
- 因为头结点放不放摄像头也就省下一个摄像头, 叶子节点放不放摄像头省下了的摄像头数量是指数阶别的。
- **所以我们要从下往上看,局部最优:让叶子节点的父节点安摄像头,所用摄像头最少,整体最优:全部摄像头数量所用最少!**从下往上但是是从叶子结点的上一层开始。
-
如何隔两个节点放一个摄像头
- 我们分别有三个数字来表示:
- 0:该节点无覆盖
- 1:本节点有摄像头
- 2:本节点有覆盖
- 因为叶子节点的两个空节点为有覆盖时,才好跳过叶子结点放置监控,所以空节点状态应该成为有覆盖。
- 具体情况的判断建议去看看卡尔的推导。
-
解题代码
- c++
-
// 版本一 class Solution { private: int result; int traversal(TreeNode* cur) { // 空节点,该节点有覆盖 if (cur == NULL) return 2; int left = traversal(cur->left); // 左 int right = traversal(cur->right); // 右 // 情况1 // 左右节点都有覆盖 if (left == 2 && right == 2) return 0; // 情况2 // left == 0 && right == 0 左右节点无覆盖 // left == 1 && right == 0 左节点有摄像头,右节点无覆盖 // left == 0 && right == 1 左节点有无覆盖,右节点摄像头 // left == 0 && right == 2 左节点无覆盖,右节点覆盖 // left == 2 && right == 0 左节点覆盖,右节点无覆盖 if (left == 0 || right == 0) { result++; return 1; } // 情况3 // left == 1 && right == 2 左节点有摄像头,右节点有覆盖 // left == 2 && right == 1 左节点有覆盖,右节点有摄像头 // left == 1 && right == 1 左右节点都有摄像头 // 其他情况前段代码均已覆盖 if (left == 1 || right == 1) return 2; // 以上代码我没有使用else,主要是为了把各个分支条件展现出来,这样代码有助于读者理解 // 这个 return -1 逻辑不会走到这里。 return -1; } public: int minCameraCover(TreeNode* root) { result = 0; // 情况4 if (traversal(root) == 0) { // root 无覆盖 result++; } return result; } }; // 版本二 class Solution { private: int result; int traversal(TreeNode* cur) { if (cur == NULL) return 2; int left = traversal(cur->left); // 左 int right = traversal(cur->right); // 右 if (left == 2 && right == 2) return 0; else if (left == 0 || right == 0) { result++; return 1; } else return 2; } public: int minCameraCover(TreeNode* root) { result = 0; if (traversal(root) == 0) { // root 无覆盖 result++; } return result; } }; - golang
-
const inf = math.MaxInt64 / 2 func minCameraCover(root *TreeNode) int { var dfs func(*TreeNode) (a, b, c int) dfs = func(node *TreeNode) (a, b, c int) { if node == nil { return inf, 0, 0 } lefta, leftb, leftc := dfs(node.Left) righta, rightb, rightc := dfs(node.Right) a = leftc + rightc + 1 b = min(a, min(lefta+rightb, righta+leftb)) c = min(a, leftb+rightb) return } _, ans, _ := dfs(root) return ans } func min(a, b int) int { if a <= b { return a } return b }