单调递增的数字
这道题思路挺巧妙的。举个例子,332这个数,会出现strNum[i - 1] > str[i]
这种非单调递增的情况,这时需要将strNum[i - 1]--
,然后给strNum[i]
赋值9,这样既保证了两位数字之间的递增关系,同时也使得数字减小的最少。
- 最后的问题就是处理的方向,如果从前向后遍历,其实并不能维持单调递增的性质(举例模拟一下可知),没法利用之前的比较结果。所以需要从后向前遍历。
- 另外就是该给哪些位赋9,一旦某一位需要被赋值为9,那这一位后面都应该被赋值9,因为要保证这个数要小于等于原来的数。
class Solution{
public:
int monotoneIncreasingDigits(int n){
string strNum = to_string(n);
int flag = strNum.size(); // 确定从哪一位开始被赋值为9,赋初始值,避免循环出错
for(int i = strNum.size() - 1; i > 0; i--){
if(strNum[i - 1] > strNum[i]){
// 出现了非单调递增的情况
strNum[i - 1]--;
flag = i; // 第i位应该赋值为9
}
}
for(int i = flag; i < strNum.size(); i++){
strNum[i] = '9';
}
return stoi(strNum);
}
};
监控二叉树
一个摄像头可以覆盖上中下三层,如果摄像头放在叶子节点上就损失了一层覆盖,所以将摄像头放在叶子节点的父节点位置,才能充分利用摄像头的覆盖面积。
所以我们要从树的底层开始向上遍历,局部最优:让叶子节点的父节点安摄像头,所用摄像头最少。整体最优:所用的全部摄像头数目最少。
具体到实现上:
- 二叉树的遍历
- 每隔两个节点放一个摄像头
这里从底层开始,需要后序遍历。那么如何每隔两个节点放一个摄像头,这里利用状态转移的方法。每一个节点都有一个对应的状态,是 “0-无覆盖;1-有摄像头;2-有覆盖” 三种之一。
那么空节点的状态应该是什么呢?如果赋值为0,那么叶子节点就需要放摄像头,这不符我们的要求;如果赋值为1,那么下一个摄像头应该放在叶子节点的爷爷节点,这也不对。所以只能给空节点赋值为2,叶子节点的父节点是需要摄像头的,合理!
另外还有一个最终的头结点问题,如果覆盖了或者有摄像头还好,但如果没覆盖,就需要一个摄像头。
class Solution{
public:
int result = 0;
int traversal(TreeNode* cur){
if(cur == nullptr) return 2;
int left = traversal(cur->left);
int right = traversal(cur->right);
if(left == 0 || right == 0){ // 如果左右节点中有没覆盖的,所以当前的节点应该安摄像头
result++;
return 1;
}
if(left == 1 || right == 1){ // 如果左右节点中有摄像头,那么当前的节点应该有覆盖
return 2;
}
if(left == 2 && right == 2){
return 0;
}
return -1;
}
int minCameraCover(TreeNode* root){
if(traversal(root) == 0){
result++; // 如果头节点没有被覆盖,摄像头的数目应该+1
}
return result;
}
};