LeetCode 860.柠檬水找零
题目链接:860.柠檬水找零
踩坑:以为不需要考虑具体怎么找钱,一直在从整体上想解决方案。
思路:当客户支付5元我们只需要收下,当客户支付10元我们只能找零5元,当客户支付20元我们优先找零一个10元一个5元,如果不行也只能支付三个5元。可以看到所有的模式相对比较固定,所以可以直接模拟。
代码:
class Solution {
public:
bool lemonadeChange(vector<int>& bills) {
int five = 0;
int ten = 0;
for(int i = 0; i < bills.size(); i++)
{
if(bills[i] == 5) five++;
else if(bills[i] == 10)
{
five--;
if(five < 0) return false;
ten++;
}
else if(bills[i] == 20)
{
if(ten > 0 && five > 0)
{
ten--;
five--;
}
else if(five > 2) five = five - 3;
else return false;
}
}
return true;
}
};
LeetCode 406.根据身高重建队列
题目链接:406.根据身高重建队列
踩坑:看到了类似分发糖果那题不要两边同时考虑的提示,但是没有完全理解“两边”的含义。
思路:加深了对于有多个排序依据的题目的理解。在分发糖果那题中,分发的依据分别是左边的孩子得分和右边孩子的得分。在本题中,排序的依据分别为身高和希望前面有多少人没自己低。因此,所谓的不要不要两边同时考虑的意思其实是先确定一个条件,再确定另一个。所以,所有人应先根据身高从高到低排序(因为第二个条件在意的是前面有多少人没自己低),如果身高一样则根据第二个条件从低到高排(这样更符合题意)。这样会得到一个按身高从高到低的排序,此时根据第二个条件将后面的人插到符合的位置。因为前面的人都比后面的人高,所以后面的人插到前面的队伍里并不会影响前面的人的第二个条件。
代码:
class Solution {
public:
static bool cmp(vector<int> a, 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) {
vector<vector<int>> result;
sort(people.begin(), people.end(), cmp);
for(int i = 0; i < people.size(); i++)
{
result.insert(people[i][1] + result.begin(), people[i]);
}
return result;
}
};
LeetCode 452.用最少数量的箭引爆气球
题目链接:452.用最少数量的箭引爆气球
踩坑:想到要根据x从小到大排序了,但是陷入了射箭策略的陷阱,比如[1,10],[1,2],[5,8],[5,6]这种情况应该先射爆两个还是三个,以为有更节省的策略但其实都一样。
思路:根据x从小到大排序,判断相交后更新相交区间。
代码:
class Solution {
public:
static bool cmp(vector<int>& a, vector<int>& b)
{
return a[0] < b[0];
}
int findMinArrowShots(vector<vector<int>>& points) {
if(points.size() == 0) return 0;
int result = 1;
sort(points.begin(), points.end(), cmp);
for(int i = 0; i < points.size()-1; i++)
{
if(points[i][1] < points[i+1][0]) result++;
else
{
points[i+1][1] = min(points[i][1], points[i+1][1]);
}
}
return result;
}
};