算法思想-贪心
利用贪心思想解题的最大难点在于证明贪心的选择是最优的。常用的证明方法:反证法、数学归纳法
- 不重叠的区间个数 435. Non-overlapping Intervals(Medium)
- 投飞镖刺破气球452. Minimum Number of Arrows to Burst Balloons(Medium)
- 根据身高和序号重组队列 406. Queue Reconstruction by Height(Medium)
- 修改一个数成为非递减数组665. Non-decreasing Array(Medium)
- 分隔字符串使同种字符出现在一起763. Partition Labels(Meidum)
不重叠的区间个数
典型的贪心,先按结束时间排序,然后依次选择。
证明:如果不先选结束最早的,选择一个结束第k早的,那么接下来可选的时间范围变为了[k_end,end],1_end < k_end,如果[k_end,end]中答案为m,[1_end,end]的答案肯定大于等于m,所以应该选结束最早的。(i_end表示结束时间排在第i位的活动的结束时间,end表示最晚时间)
bool cmp(vector<int>& a, vector<int>& b){
if(a[1] != b[1])
return a[1] < b[1];
return a[0] < b[0];
}
class Solution {
public:
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
int n = intervals.size();
if(n == 1)
return 0;
int left = 0;
sort(intervals.begin(), intervals.end(), cmp);
int max_t = intervals[0][1];
left += 1;
for(int i = 1;i < n; i++){
if(intervals[i][0] >= max_t){
max_t = intervals[i][1];
left += 1;
}
}
return n-left;
}
};
投飞镖刺破气球
bool cmp(vector<int>& a, vector<int>& b){
if(a[1] != b[1])
return a[1] < b[1];
return a[0] < b[0];
}
class Solution {
public:
int findMinArrowShots(vector<vector<int>>& points) {
sort(points.begin(), points.end(), cmp);
int ans = 1;
int end = points[0][1];
for(int i = 1;i < points.size(); i++){
if(points[i][0] <= end)
continue;
end = points[i][1];
ans += 1;
}
return ans;
}
};
根据身高和序号重组队列
已知逆序数数组求原排列
选用list方便进行快速插入
bool cmp(vector<int>& a, vector<int>& b){
if(a[0] != b[0])
return a[0] > b[0];
return a[1] < b[1];
}
class Solution {
public:
vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
sort(people.begin(), people.end(), cmp);
list<vector<int>> q;
for(int i = 0;i < people.size(); i++){
list<vector<int>>::iterator it = q.begin();
int pos = people[i][1];
while(pos--)
it++;
q.insert(it, people[i]);
}
vector<vector<int>> ans;
for(auto it: q)
ans.push_back(it);
return ans;
}
};
买卖股票最大的收益
遍历数组,curr表示当前已知的最低价,遇到更低的则更新curr,否则更新profit
买卖股票的最大收益 II
贪心:有钱赚就卖,卖了马上再买
子数组最大和
求和,和为负值后重新开始。
分隔字符串使同种字符出现在一起
统计每个字符串出现的最远位置,遍历字符串的每个字符,如果当前位置前面的所有字符出现的最远位置都没有超过当前位置则可以划分。
class Solution {
public:
vector<int> partitionLabels(string s) {
int maxpos[26];
for(int i = 0;i < s.size(); i++)
maxpos[s[i] - 'a'] = i;
int i = 0, start = 0, end = 0;
vector<int> ans;
while(i < s.size()){
end = max(end, maxpos[s[i] - 'a']);
if(end <= i){
ans.push_back(end-start+1);
start = i+1;
}
i += 1;
}
return ans;
}
};
修改一个数成为非递减数组
参考链接:https://leetcode-cn.com/problems/non-decreasing-array/solution/yi-ding-yao-rang-ni-nong-dong-wei-shi-ya-u9te/
class Solution {
public:
bool checkPossibility(vector<int>& nums) {
if(nums.size() == 1)
return true;
int change = nums[1] >= nums[0] ? 0 : 1;
for(int i = 1;i < nums.size()-1; i++){
if(nums[i] > nums[i+1]){
if(change == 0){
if(nums[i+1] >= nums[i-1])
nums[i] = nums[i+1];
else
nums[i+1] = nums[i];
change = 1;
}
else
return false;
}
}
return true;
}
};
1266

被折叠的 条评论
为什么被折叠?



