56. 合并区间
将当前结果暂存于结果集中,并随着遍历而修改结果集。这样就省去了记录左右边界的问题。
cpp
class Solution {
static bool cmp(vector<int>& a, vector<int>& b) {
if (a[0] == b[0])
return a[1] > b[1];
else
return a[0] < b[0];
}
public:
vector<vector<int>> merge(vector<vector<int>>& intervals) {
vector<vector<int>> result;
sort(intervals.begin(), intervals.end(), cmp);
result.push_back(intervals[0]);
for (int i = 1; i < intervals.size(); ++i) {
if (intervals[i][0] <= result.back()[1]) {
result.back()[1] = max(intervals[i][1], result.back()[1]);
}
else {
result.push_back(intervals[i]);
}
}
return result;
}
};
738.单调递增的数字
本题的策略是遇到前一位大于后一位的情况,前一位减一,后面的置为9。本题有两个易错点:
- 遍历顺序。如果是从前往后遍历,有可能出现332变为329的情况,也就是说后面的符合条件了,但是前面部分不符合条件了。
- 要记录最终要修改为9的位置。如果仅仅是将后一位置为9,遇到100就只会得到90而不是99.
cpp
class Solution {
public:
int monotoneIncreasingDigits(int n) {
string result = to_string(n);
int flag = result.size();
for (int i = result.size() - 1; i > 0; --i) {
if (result[i] < result[i - 1]) {
result[i - 1]--;
flag = i;
}
}
for (int i = flag; i < result.size(); ++i) {
result[i] = '9';
}
return stoi(result);
}
};
968.监控二叉树
贪心策略:叶子节点的父节点尽量安装摄像头;每隔两个空节点安装摄像头。
怎么实现呢?
- 给每个节点都设置状态,一共有三种状态。
0:该节点未被覆盖
1:有摄像头
2:有覆盖 - 确定二叉树遍历顺序。因为要根据子节点的状态来决定是否要安装摄像头,因此采取后序遍历。
- 确定终止条件:遇到空节点返回有覆盖2。
- 单层处理逻辑:
- 左右孩子都有覆盖,返回未覆盖0
- 左右孩子有未覆盖,安装摄像头,返回1
- 左右孩子有摄像头,返回已覆盖,返回2
- 根节点返回未覆盖0,安装摄像头。
cpp
class Solution {
public:
int result = 0;
// 0:未覆盖
// 1:有摄像头
// 2:已覆盖
int traversal(TreeNode* node) {
if (node == nullptr)
return 2;
int left = traversal(node->left);
int right = traversal(node->right);
if (left == 2 && right == 2)
return 0;
if (left == 0 || right == 0) {
result++;
return 1;
}
if (left == 1 || right == 1) {
return 2;
}
return -1;
}
int minCameraCover(TreeNode* root) {
result = 0;
if (traversal(root) == 0)
result++;
return result;
}
};