第一部分:860.柠檬水找零
1.1题目链接
力扣https://leetcode.cn/problems/lemonade-change/
1.2解题思路
我的思路:
分情况:顾客拿5元的直接收进来。拿10元的,用5元找零。拿20元的,首先找零5+10,或者直接找零三个5.
代码随想录思路:
所以局部最优:遇到账单20,优先消耗美元10,完成本次找零。全局最优:完成全部账单的找零。
局部最优可以推出全局最优。
1.3解题代码
class Solution {
public:
bool lemonadeChange(vector<int>& bills) {
int charge[2];
for(int i = 0; i < bills.size(); i++){
if(bills[i] == 5) charge[0] += 5;
if(bills[i] == 10) {
charge[0] -= 5;
if(charge[0] < 0){
return false;
}
charge[1] += 10;
}
if(bills[i] == 20){
charge[0] -= 5;
if(charge[1] != 0) charge[1] -= 10;
else charge[0] -= 10;
if(charge[0] < 0 || charge[1] < 0){
return false;
}
}
}
return true;
}
};
第二部分:406.根据身高重建队列
2.1题目链接
力扣https://leetcode.cn/problems/queue-reconstruction-by-height/
2.2解题思路
本题有两个维度,h和k,看到这个题一定要想到如何确定一个维度,
然后再按照另一个维度重新排序。
本题目先按照身高排序:
身高从大到小(身高相同的k小的站在前面)
按照k值进行插入
按照身高排序之后,有限按身高高的人people的k来插入,后续插入节点也不会影响到前面已经插入的节点。
局部最优:优先按身高的people的k来插入。插入操作后的people满足队列的属性。
全局最优:最后都做完插入操作,这个队列满足题目队列属性。
2.3解题代码
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;
for(int i = 0; i < people.size(); i++){
int position = people[i][1];
que.insert(que.begin() + position, people[i]);
}
return que;
}
};
第三部分:452.用最少数量的箭引爆气球
3.1题目链接
力扣https://leetcode.cn/problems/minimum-number-of-arrows-to-burst-balloons/
3.2解题思路
局部最优:当气球出现重叠,一起射,所用的弓箭最少。
全局最优:把所有的气球射爆所用的弓箭最小。
如何模拟气球射爆的过程?是在数组中移除元素还是做标记呢?
仔细思考如果把气球排序之后,从前遍历气球,被射过的气球仅仅跳过就行了,没有必要让气球移除。只要记录一下箭的数量就行。
为了尽可能让气球重叠,需要对数组进行排序。那么按照气球起始位置还是按照气球终止位置排序呢?
其实都可以,如果按照起始位置排序,那么就从前向后遍历气球数组。
从前向后遍历遇到重叠的气球了怎么办?
如果气球重叠了,重叠气球中右边边界的最小值之前的区域一定需要一个弓箭。
3.3解题代码
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 result = 1;//points不为空,那么至少需要一只箭
for(int i = 1; i < points.size(); i++){
if(points[i][0] > points[i-1][1]){
result++;//需要一只箭
}
else{
points[i][1] = min(points[i-1][1], points[i][1]);//更新重叠气球的最小右边界
}
}
return result;
}
};