题目链接: 738.单调递增的数字
对于char
进行减法时,想要通过数字相减再转化为对应的字符,需要再加上个’0’
char a = '9';
char b = a - '1';//error
char c = a - '1' + '0';
a--;//满足要求
class Solution {
public:
int monotoneIncreasingDigits(int n) {
string s = to_string(n);
int flag = s.size();//记录从哪开始都是9
for (int i = s.size() - 1; i > 0; --i) {
if (s[i - 1] > s[i]) {
s[i - 1]--;//直接在s上修改
flag = i;
}
}
for (int i = flag; i < s.size(); ++i) {
s[i] = '9';
}
return stoi(s);
}
};
题目链接:968.监控二叉树
贪心策略:优先在叶子节点的父节点放置摄像头,然后每两个节点放置一个摄像头,往根节点推。
从根节点开始出发,因此采用后序遍历。
每个节点可分为三个状态:无覆盖0、有摄像头1和有覆盖2(无覆盖和有摄像头+有覆盖是互斥事件)。
还要考虑一下空节点(因为在递归的终止条件是对空节点的判断),为了满足贪心策略,空节点只能是有覆盖2。
节点状态转移,有以下情况:
最终所有节点不能是无覆盖0状态。
特殊情况:所以当第一种情况发生时,该情况下的父节点为根节点时,需要将根节点设置为有摄像头1;
第二种情况也包含无覆盖0,但是当父节点为有摄像头1时,已经去掉了无覆盖0状态。
上述三种情况中,第二条和第三条是有严格的优先顺序
,当第二条执行完毕,第三条的条件就为左右孩子一定不是无覆盖的前提下再判断。
class Solution {
int res = 0;
int/*返回状态*/ recursive(TreeNode* cur) {
if (!cur) return 2;//终止条件
int left = recursive(cur->left);//左
int right = recursive(cur->right);//右
//中
if (left == 2 && right == 2) return 0;//情况一
if (left == 0 || right == 0) {//情况二
++res;
return 1;
}
if (left == 1 || right == 1) return 2;//情况三
return -1;//与题意无关,满足非空返回函数,当其他条件都不满足时,需要有返回值
}
public:
int minCameraCover(TreeNode* root) {
if (recursive(root) == 0/*特殊情况*/)
++res;
return res;
}
};
对于return -1;
语句说明的是,根据设计逻辑上不可能执行到该语句。但因为编程语言为了满足if
的完整性,从而要求的,可以将该语句改为else return -1;
,从而满足了if
的完整性。
或者可以将中这一判断中的三个if
整合为
if (left == 2 && right == 2) //情况一
return 0;
else if (left == 0 || right == 0) {//情况二
++res;
return 1;
} else //情况三
return 2;
也可以满足if
完整性,可以省略掉return -1
。但是代码可读性差。
主要还是看局部贪心策略的选取吧,是否能推到全局最优,而且没有明显的反例,试一下,如果通过了,证明策略满足要求。