前言
LeetCode题目:LeetCode 860、406、452
Takeaway:贪心算法,需要考虑多个角度的贪心算法题,应该先从一个角度贪心,确定后再考虑另一个角度的贪心;以及重叠区间问题的贪心解法。
一、860
挺简单的一道题,贪心逻辑就是:5元钱最宝贵,能先用10元就先用10元。
class Solution {
public:
bool lemonadeChange(vector<int>& bills) {
int money5 = 0;
int money10 = 0;
for(int i=0; i<bills.size(); i++) {
if(bills[i] == 5){
money5++;
}
if(bills[i] == 10){
money10++;
if(money5 == 0){
return false;
}
money5--;
}
if(bills[i] == 20){
int curMoney = 15;
if(money10 > 0){
curMoney -= 10;
money10--;
}
while(curMoney>0 && money5 > 0){
curMoney -= 5;
money5--;
}
if(curMoney>0 && money5 == 0){
return false;
}
}
}
return true;
}
};
二、406
和昨天的分糖问题有点像,需要从两种角度考虑贪心思路,本题第一阶段贪心就是先按照身高排序,第二阶段贪心就是复制到一个新的数组里,但是高的先插入,矮的后插入,这样不会影响结果。如果反着来的话,后插入的高的会破坏已经插入好的结果。
class Solution {
public:
static bool cmp(const vector<int>& a, const vector<int>& b) {
//身高一样的话,前面没人的排在前面
if (a[0] == b[0])
return a[1] < b[1];
return a[0] > b[0];
}
vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
//身高高的在最前面
sort (people.begin(), people.end(), cmp);
//返回结果
vector<vector<int>> que;
//这种方法插入能成功的原因是,高的先插入,这样当矮的插入到高的前方时,不会改变两者的 k 值(前面有多少个更高的人)
for(int i=0; i<people.size(); i++){
int position = people[i][1];
que.insert(que.begin() + position, people[i]);
}
return que;
}
};
三、452
重叠区间问题,本题最巧妙的地方在于points[i][1] = min(points[i - 1][1], points[i][1]);,合并结束位置为最小的那个,这样就可以保证一箭能射到尽可能多的气球,不满足的话,就一定要再射一箭。
class Solution {
public:
static bool cmp(const vector<int>& a, const vector<int>& b) {
return a[0] < b[0];
}
int findMinArrowShots(vector<vector<int>>& points) {
if (points.size() == 0)
return 0;
sort(points.begin(), points.end(), cmp);
int ans = 1;
for(int i=1; i<points.size(); i++){
if(points[i-1][1] < points[i][0]){
ans++;
}else{
// 这里写的太好了,合并了结束的区间,统一用最小的那个
points[i][1] = min(points[i - 1][1], points[i][1]);
}
}
return ans;
}
};
总结
贪心算法,需要考虑多个角度的贪心算法题,应该先从一个角度贪心,确定后再考虑另一个角度的贪心;以及重叠区间问题的贪心解法。