【算法/贪心算法/有点难度题】题解+详细备注(共3题)
53.最大子数组和
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int result{INT_MIN};
int numSum{};
int n = nums.size();
for(int i{};i<n;++i){
numSum+=nums[i];
if(numSum > result) result = numSum; // 取区间累计的最大值
if(numSum < 0) numSum = 0; // 重置最大子序起始位置
}
return result;
}
};
134.加油站
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int totalNum{}; // 总油量-总消耗
int curNum{}; // 当前区间的总油量-总消耗
int start{}; // 从下标0开始尝试
for(int i{};i<gas.size();++i){
curNum += gas[i] - cost[i];
totalNum += gas[i] - cost[i];
if(curNum < 0){ // 当前累加油与消耗抵消后的和 curSum一旦小于0,说明当前区间作为起始位置,是肯定不符合条件的,继续更新起始坐标即可
start = i+1; // 起始位置更新为i+1(如果依然不满足,就继续更新,直到将所有位置都当作起始位置尝试一遍)
curNum = 0; // curSum从0开始
}
}
// 总油量大于总消耗量,说明可以走完一整圈
// 否则说明怎么走都不可能跑一圈了
if(totalNum < 0) return -1;
return start;
}
};
968.监控二叉树
class Solution {
public:
int result{};
// 重要:要根据题意确定倒是什么样的遍历是合适的
// 使用后序遍历 0无覆盖 1摄像头 2有覆盖
int traversal(TreeNode*root){
// 空节点,该节点有覆盖
if(!root) return 2;
int left = traversal(root->left);
int right = traversal(root->right);
// 情况1
// 左右节点都有覆盖
if(2==left && right == 2){
return 0;
}
// 情况2
// left == 0 && right == 0 左右节点无覆盖
// left == 1 && right == 0 左节点有摄像头,右节点无覆盖
// left == 0 && right == 1 左节点有无覆盖,右节点摄像头
// left == 0 && right == 2 左节点无覆盖,右节点覆盖
// left == 2 && right == 0 左节点覆盖,右节点无覆盖
if(left ==0 || right == 0){
result++;
return 1;
}
// 情况3
// left == 1 && right == 2 左节点有摄像头,右节点有覆盖
// left == 2 && right == 1 左节点有覆盖,右节点有摄像头
// left == 1 && right == 1 左右节点都有摄像头
// 其他情况前段代码均已覆盖
if(left == 1 || right == 1){
return 2;
}
return -1;
}
int minCameraCover(TreeNode* root) {
// 情况4 root无覆盖
if(traversal(root) == 0){
result++;
}
return result;
}
};