#738 单调递增的数字
30min 自己想的是O n^2 也能过
int monotoneIncreasingDigits(int n) {
if(n<10) return n;
if(n==10) return 9;
string numstr=to_string(n);
int pos=-1;
for(int i=0;i+1<numstr.size();i++){
if(numstr[i+1]<numstr[i] && pos==-1) pos=i;
}
if(pos==-1) return n;
//now has conflict
while(pos>=0){
//pos[] -1, after 9
numstr[pos]=numstr[pos]-1;
for(int i=pos+1;i<numstr.size();i++) numstr[i]='9';
if(pos==0) break;
if(pos>0){
if(numstr[pos-1]<=numstr[pos]) break;
else pos--;
}
}
return stoi(numstr);
}
补充一个小插曲:初写出来run是TLE,其实TLE也不代表是自己想出来的算法复杂度有问题,直接思路不行。有可能是code某处没写对,死循环了,所以还可以改进对的。然后又出现了和加油站那题一样,在run状态下,某个case TLE 之后,再跑别的case出现不正常不合理的结果,这可能是leetcode编译资源没更新。这时只需要去submit再跑一次就好了,就不会出现诡异的结果了。
改进:每次找到conflict位置后,不用急于把后面都改成9.反正一轮一轮会不断向前更新conflict位置。等找完了更新完毕,再一起把后面都改成9. 而且仔细看看自己的逻辑会发现,不用处理开头那些特殊情况。倒是 10 会变成09,但是 stoi 也还是能变成9的。
于是进行了以上的改进就把 O n ^2 变成了 O n, 变成和随想录一样的了
int monotoneIncreasingDigits(int n) {
string numstr=to_string(n);
int pos=-1;
for(int i=0;i+1<numstr.size();i++){
if(numstr[i+1]<numstr[i] && pos==-1) pos=i;
}
if(pos==-1) return n;
//now has conflict
while(pos>=0){
//pos[] -1, after 9
numstr[pos]=numstr[pos]-1;
//for(int i=pos+1;i<numstr.size();i++) numstr[i]='9';
if(pos==0) break;
if(pos>0){
if(numstr[pos-1]<=numstr[pos]) break;
else pos--;
}
}
//return stoi(numstr);
for(int i=pos+1;i<numstr.size();i++){
numstr[i]='9';
}
return stoi(numstr);
}
#968.监控二叉树 Hard
一开始忘了是贪心,当做dp去做了。其实也可以做,也是要用这三种状态
随想录的思路的代码:
int result;
int traversal(TreeNode* cur) {
// status num:
// 0 not covered
// 1 have cam
// 2 yes covered
// !! special: null == covered
//因为设置成 0 1 都不对
if (cur == NULL) return 2;
int left = traversal(cur->left); // 左
int right = traversal(cur->right); // 右
// 情况1
// 左右节点都有覆盖,那他们就没有摄像头,是间接被覆盖的,不能覆盖别人
//所以 parent没被覆盖
if (left == 2 && right == 2) return 0;
// 情况2
//只要有一个孩子没被覆盖,parent就要放摄像头
if (left == 0 || right == 0) {
result++;
return 1;
}
// 情况3
//只要有一个child有摄像头,parent就被覆盖
if (left == 1 || right == 1) return 2;
// 这个 return -1 逻辑不会走到这里。
return -1;
}
int minCameraCover(TreeNode* root) {
result = 0;
// 情况4
if (traversal(root) == 0) { // root 无覆盖
result++;
}
return result;
}
思路产生的逻辑:leaf node不能放cam->leaf parent要放 cam -> 往上遍历,child parent 间隔一个放一个cam (这是局部最优)
需要建立以下状态:而且要注意dp是有择优的,但是贪心就是单纯的状态转移
还有个要点是,空node要设置成被覆盖,才合理(其实我觉得 再弄个数字作为第四种状态,也可以,就是逻辑判断要再复杂一点)