(37/60)单调递增的数字、监控二叉树
单调递增的数字
leetcode:738. 单调递增的数字
贪心法
思路
从后往前遍历,碰到不满足单调递增的,前一位数字--,标记当前位置。
从flag(包括)往后,全部赋值为9。
复杂度分析
时间复杂度:O(N)。
空间复杂度:O(N)。
N为数字位数。
注意点
-
数字->字符串用
to_string(num)
字符串->数字用
stoi(str)
-
字符串赋值的时候赋值是字符'9'而不是数字9
代码实现
class Solution { public: // 转换成字符串方便处理 // 从后往前遍历,碰到不满足单调递增的,往前一位--,标记当前位置 // 从flag(包括)往后,全部赋值为9 // 转换回来 int monotoneIncreasingDigits(int n) { string s = to_string(n); int flag = s.size(); for(int i = s.size() - 1;i > 0;i--){ if(s[i - 1] > s[i]){ s[i-1]--; flag = i; } } for(int i = flag;i < s.size();i++) s[i] = '9'; // 注意,不能赋值为数字9而是字符9 return stoi(s); } };
监控二叉树
leetcode:968. 监控二叉树
贪心法
思路
放置的策略:
- 非叶子节点。要不然就浪费了上中下三层监视范围。
- 要全部覆盖。
采用后序遍历,根据左右子树递归后向上返回的值进行处理。
定义状态 0-无覆盖 1-摄像头 2-有覆盖
根据左右子树不同值有三种情况,对应根取值为:
- 0 || 0 -> 1; 优先级最高
- 1 || 1 -> 2;
- 2 && 2 -> 0;
由于是父节点取适合的值来照顾左右子节点,节点没有父节点时(root)会出现异常,所以最后再检查一下root是否被覆盖。
复杂度分析
时间复杂度:O(N)。
空间复杂度:递归栈深度。平衡时O(logN);极倾斜时O(N)。
注意点
- 可能左右节点一个是0、一个是2,这时候要覆盖0优先,根取1。
代码实现
后序遍历正解:
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode() : val(0), left(nullptr), right(nullptr) {} * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} * }; */ class Solution { private: int result = 0; public: // 定义状态 0-无覆盖 1-摄像头 2-有覆盖 // 后序遍历,根据左右子树不同值有三种情况,根为: // 1. 0 || 0 -> 1; 优先级最高 // 2. 1 || 1 -> 2; // 3. 2 && 2 -> 0; int postOrder(TreeNode* cur){ if(!cur) return 2; // 定义空节点状态为2,对应情况1 int left = postOrder(cur->left); int right = postOrder(cur->right); if(left == 0 || right == 0) { result++; return 1; }else if(left == 1 || right == 1){ return 2; }else{ return 0; } } int minCameraCover(TreeNode* root) { if(postOrder(root) == 0) return ++result; else return result; } };
错版~~思路是从底向上,且从倒数第二层开始,间隔一层放置摄像头。
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode() : val(0), left(nullptr), right(nullptr) {} * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} * }; */ class Solution { public: // 层序遍历,从底部往上,间隔一层放置摄像头(由下往上第二层开始放) // 层序遍历,获得每层节点数的数组 int minCameraCover(TreeNode* root) { if(!root) return 0; vector<int> vec; queue<TreeNode*> que; que.push(root); while(!que.empty()){ int size = que.size(); vec.push_back(size); while(size--){ TreeNode* cur = que.front(); que.pop(); if(cur->left) que.push(cur->left); if(cur->right) que.push(cur->right); } } if(vec.size() == 1) return 1; int sum = 0; for(int i = vec.size() - 2;i >= 0 ;i-=2 ){ sum += vec[i]; } return sum; } };
分类:
算法
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?