738.单调递增的数字
题目描述:
当且仅当每个相邻位数上的数字
x
和y
满足x <= y
时,我们称这个整数是单调递增的。给定一个整数
n
,返回 小于或等于n
的最大数字,且数字呈 单调递增 。示例 1:
输入: n = 10 输出: 9示例 2:
输入: n = 1234 输出: 1234示例 3:
输入: n = 332 输出: 299提示:
0 <= n <= 109
.
贪心思路:
当我们遍历数字的不同位数时,遇到当前位数小于后面的位数,则当前位-1,后面位取最大值,例如32,3小于2,因此-1得到2,后一位找的最大值9,因此就得出结果29,我们在遍历的时候应该由后往前遍历,因为由前往后遍历,可能后面得到的数值会比前面的小,例如332,由前向后遍历结果为329,这不符合我们的题目要求,因此我们就需要从后往前遍历,这样332遍历即先比较3和2,之后就变为了329,最后就得到的就是299
代码实现:
int monotoneIncreasingDigits(int n) { char num[12]; // 数组大小增加到12,以便容纳最大的整数9999999999及结尾的'\0' sprintf(num, "%d", n); int mark = strlen(num); // 初始化 mark 为 num 的长度,用于记录需要修改的位置 // 从倒数第二位开始向前遍历,找到第一个不满足递增条件的位置 for(int i = mark - 1; i > 0; i--) { if(num[i - 1] > num[i]) { num[i - 1]--; // 将前一位数字减1 mark = i; // 记录需要修改的位置 } } // 将 mark 位置及其后面的所有数字都修改为9 for(int j = mark; j < strlen(num); j++) { num[j] = '9'; } return atoi(num); }
968.监控二叉树
题目描述:
给定一个二叉树,我们在树的节点上安装摄像头。
节点上的每个摄影头都可以监视其父对象、自身及其直接子对象。
计算监控树的所有节点所需的最小摄像头数量。
示例 1:
输入:[0,0,null,0,0] 输出:1 解释:如图所示,一台摄像头足以监控所有节点。示例 2:
输入:[0,0,null,0,null,0,null,null,0] 输出:2 解释:需要至少两个摄像头来监视树的所有节点。 上图显示了摄像头放置的有效位置之一。提示:
- 给定树的节点数的范围是
[1, 1000]
。- 每个节点的值都是 0。
思路:
根据题目可知,一个摄像头可以覆盖上中下,即可以监控4个节点,因此我们最好在叶子节点的父节点上安装摄像头,这样最大程度的利用了摄像头的覆盖范围,之后往上回退,每隔两个节点放置一个摄像头,直到遇到根节点(局部最优),因为我们要在从下往上去遍历我们的二叉树,因此我们需要后序遍历二叉树,即左右中,依靠回溯的过程去放置摄像头,对于我们的节点,都有几个状态,即0没有被覆盖,2被覆盖,1有摄像头3个状态,我们就可以根据节点的状态来确定哪些节点需要放置摄像头,对于我们叶子节点下的空节点,我们要将其设置为被覆盖的状态,否则会导致叶子节点要放置摄像头,而我们要在叶子节点的父节点放置
节点状态转移的过程:
如果左右孩子都是有覆盖的情况下,则父节点应该是无覆盖状态,要转换为有摄像头状态
如果左右孩子至少有一个覆盖,则父节点一定要有摄像头
如果左右孩子至少有一个有摄像头,其父节点一定是有覆盖状态
如果我们遍历完了,而根节点还是无覆盖状态,我们需要加上摄像头
代码实现:
/** * Definition for a binary tree node. * struct TreeNode { * int val; * struct TreeNode *left; * struct TreeNode *right; * }; */ // 递归函数,用于遍历树的节点并确定相机的放置情况 // 返回值的意义: // 0: 当前节点的子节点均被覆盖 // 1: 当前节点放置了相机 // 2: 当前节点未被覆盖 int ph(struct TreeNode *node, int *ans) { // 如果节点为空,返回2,表示未被覆盖 if(node == NULL) return 2; // 递归遍历左子树和右子树 int left = ph(node->left, ans); int right = ph(node->right, ans); // 如果左右子树均未被覆盖,则当前节点需要放置相机 if(left == 2 && right == 2) return 0; // 如果左右子树中有至少一个节点放置了相机,当前节点被覆盖 if(left == 0 || right == 0) { (*ans)++; return 1; } // 如果左右子树中有至少一个节点未被覆盖,当前节点未被覆盖 if(left == 1 || right == 1) { return 2; } return -1; // 其他情况,返回-1 } // 主函数,计算最少需要多少个相机才能覆盖整棵树 int minCameraCover(struct TreeNode* root) { int ans = 0; // 调用递归函数,计算需要的相机数量 if(ph(root, &ans) == 0) ans++; // 如果根节点需要放置相机,则相机数量加1 return ans; // 返回相机数量 }