基础知识
- 原理: 选择每一阶段的最优解, 从而达到全局最优解
- 套路: 无, 只能举反例, 想不出反例则可以尝试用贪心算法
455. 分发饼干
思路:
- 使用贪心策略
- 每次用大饼干满足大胃口的孩子(用小饼干则会浪费)
- 或用小饼干满足小胃口的孩子
- 一定是遍历孩子, 不能遍历饼干, 否则结果不正确
- 饼干 s = [ 9, 5, 3, 1]
- 胃口 g = [10, 7, 2, 1]
- 使用饼干遍历胃口时, 一直不能满足 10, 导致会尝试用5去匹配, 最后结果为 0
class Solution {
public:
int findContentChildren(vector<int>& g, vector<int>& s) {
sort(g.begin(), g.end(), greater<int>());//孩子, 降序排列
sort(s.begin(), s.end(), greater<int>());//饼干
int index = 0; //饼干索引计数
int result = 0;
for (int i = 0; i < g.size(); i++) {
if (index >= s.size()) break; //饼干用完, 只能返回
if (g[i] <= s[index]) {
result++;
index++; //用下一个饼干匹配
}
}
return result;
}
};
//自行实现, 不太容易复现
class Solution {
public:
int findContentChildren(vector<int>& g, vector<int>& s) {
sort(g.begin(), g.end(), greater<int>());
sort(s.begin(), s.end(), greater<int>());
auto its = s.begin();
auto itg = g.begin();
int res = 0;
while (its != s.end() && itg != g.end()) {
if ( *its >= *itg) {
res++;
its++;
itg++;
} else {
itg++;
}
}
return res;
}
};
376. 摆动序列
如果连续数字之间的差严格地在正数
和负数
之间交替,则数字序列称为 摆动序列
。
第一个差(如果存在的话)可能是正数或负数。仅有一个元素或者含两个不等元素的序列也视作摆动序列。
子序列
可以通过从原始序列中删除一些(也可以不删除)元素来获得,剩下的元素保持其原始顺序。
给你一个整数数组 nums
,返回 nums
中作为 摆动序列 的 最长子序列的长度
思路:
- 对于是否单调或递增, 使用 nums[i - 1] 和 nums[i] 来判断
- 局部最优: 删除单调坡上的元素
特殊情况:
- 只有一个元素, 直接返回
- 只有两个元素的情况, 不相同则返回 2 个
- 上下坡有平坡
未完全了解去相同元素的方法 , 目前强行去重
class Solution {
public:
int wiggleMaxLength(vector<int>& nums) {
vector<int> tem;
for (int i = 0; i < nums.size(); i++) {
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
tem.push_back(nums[i]);
}
nums = tem;
//元素数量 <= 2
if (nums.size() == 1) return 1;
if (nums.size() == 2) {
return nums[0] != nums[1] ? 2:1;
}
//需要元素数量 >= 3
int result = 0;
for (int i = 0; i < nums.size(); i++) {
if (i == 0) {
result++;
continue;
}
if (i == nums.size() - 1) {
result++;
continue;
}
if (nums[i - 1] < nums[i] && nums[i] > nums[i + 1]) {
result++;//极大值
} else if (nums[i - 1] > nums[i] && nums[i] < nums[i + 1]) {
result++;//极小值
}
}
return result;
}
};
53. 最大子序和
给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
子数组 是数组中的一个连续部分。
题解
思路:
- 使用 sum 做贪心
- 若相加后 sum > 0, 则判断最大值的更新
- 若相机后 sum < 0, 则舍弃该元素, 从下一个元素开始遍历
- 期间一直更新max的值
- 累计和为 正数会对值有增加的作用, 需要保留
特例:
- [-1 -2 -3] 首元素直接特例更新
- [10 -1 -11 12] 最大[12] 这段
- [10 -1 -11 2] 最大[10] 这段
- [10 -1 -8 2] 最大[10 -1 -8 2] 这段
- 只要 sum >=0 可以继续往下相加, 否则从下一个元素开始
- 当 sum 可以继续往下相加时, 需要持续更新 max 的值
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int res = 0;
int sum = 0;
for (int i = 0; i < nums.size(); i++) {
sum += nums[i];
res = max(res, sum);
if (i == 0) res = sum;
if (sum < 0) sum = 0;//从下一个数开始
}
return res;
}
};