1. 柠檬水找零
思路分析
只需要维护三种金额的数量,5,10和20。
有如下三种情况:
- 情况一:账单是5,直接收下。
- 情况二:账单是10,消耗一个5,增加一个10
- 情况三:账单是20,优先消耗一个10和一个5,如果不够,再消耗三个5
局部最优的最佳就是:每次都优先消耗最大的,万能的最后用
class Solution {
public:
bool lemonadeChange(vector<int>& bills) {
int five =0,ten=0,twenty = 0;
for(int bill : bills)
{
if(bill == 5) five++;
if(bill == 10 )
{
if(five < 0) return false;
five--;
ten++;
}
if(bill == 20)
{
if(ten > 0 & five > 0)
{
ten--;
five--;
twenty++;
}
else if(five >= 3){
five -= 3;
twenty++;
}
else return false;
}
}
return true;
}
};
时间复杂度O(N)
空间复杂度O(1)
2.根据身高重建队列
思路分析:
这道题的思路是什么呢?第一个元素是身高,第二个元素是大于等于自己身高的人
那我们是按身高排序,还是按大于自己的身高的人数排序呢?
两个一起考虑反而不行,那我们不妨这么去尝试
1. 先按身高越高的排在前面,如果身高相同就按第二个元素小的排在前面
这样是不是就满足元素一定比前面的低,比后面的要高。
那么当后面的元素要放到前面的时候,是不是也满足第二个元素的个数,也就是比他高的人数还是不变的。
2.在根据每个数组的第二个元素进行插入到对应的位置
比如[6,1]就插入到下标为1的位置[5,0]就插入到下标为0的位置
最后你可以在练习本上写写,就发现是可以的
class Solution {
public:
static bool compare(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(),compare);
//按照第二个元素逐个插入对应的位置
vector<vector<int>> vec;
for(int i=0;i<people.size();i++)
{
//找到第二个数
int index = people[i][1];
vec.insert(vec.begin()+index,people[i]);
}
return vec;
}
};
这个是贪心思路,和分发糖果一样,都是两个维度中,先满足一个维度,在去满足第二个维度.
局部最优就是,前面的元素比自己大,后面的元素的身高比自己小。
每次进行插入的时候都会满足前面数组中比自己身高高的人数的个数。
疑问解决:vector初始化的时候,底层就会自己开辟一些空间,当个数超过这个空间的时候会进行自动的扩容。这里会随着数据量的增大浪费一些时间和空间,可以用链表List来实现。
可以看看分发糖果问题分发糖果