代码随想录第35天| 贪心4
860.柠檬水找零(简单)
这题思路比较简单,一共三种情况
遇到5块,收了: five++
遇到10块,ten++, 找5块,five–
遇到20,先考虑10块和5块的组合,因为10块只能给20的找;ten–, five–
如果10块不够,考虑三张5块的找法,如果还不行就return false
class Solution {
public:
/*
1.收5块的
2.遇到10块,five--, ten++
3.遇到20,优先用10和5,若没有10,five-3
*/
bool lemonadeChange(vector<int>& bills) {
int five = 0, ten = 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--;
} else if(five >= 3){
five -= 3;
}else
return false;
}
}
return true;
}
};
406.根据身高重建队列 (中)
LeetCode题目: 406.根据身高重建队列
代码随想录:406.根据身高重建队列
题读了半天没读懂,直接看解析了。。
1.先对身高从大到小排序,若身高相同,k小的在前。 先保证了每个人前面没有比自己矮的
2.再用K对整个队列进行调整,每个人插入的位置是ki(因为每个人都没有自己前面的人高,所以插到前面时,不会影响插入位置的后面的人排序,保证了k符合要求)
有点像基数排序
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 pos = people[i][1];
que.insert(que.begin() + pos, people[i]);
}
return que;
}
};
时间复杂度:O(nlog n + n2)
空间复杂度:O(n)
vector的插入操作非常耗时。C++中vector(可以理解是一个动态数组,底层是普通数组实现的)如果插入元素大于预先普通数组大小,vector底部会有一个扩容的操作,即申请两倍于原先普通数组的大小,然后把数据拷贝到另一个更大的数组上。
所以使用vector(动态数组)来insert,是费时的,插入再拷贝的话,单纯一个插入的操作就是O(n2)了,甚至可能拷贝好几次,就不止O(n2)了。
因此可以改成链表list实现
// 版本二
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);
list<vector<int>> res;
for(int i = 0; i < people.size(); i++){
int pos = people[i][1];
auto it = res.begin();
advance(it, pos); // 迭代器向前移动pos个单位
res.insert(it, people[i]);
}
return vector<vector<int>>(res.begin(), res.end());
}
};
452. 用最少数量的箭引爆气球 (中)(重叠区间)
LeetCode题目: 452. 用最少数量的箭引爆气球
代码随想录: 452. 用最少数量的箭引爆气球
b站视频
思路太巧妙了。贪心的想法是对重叠的气球尽量用同一个箭来射。
问题在于如何判断两个气球是否重叠,以及如果重叠,是否跟下一个气球也重叠。
1.先对所有气球按照左边界排个序,方便遍历。
2.如果当前左边界>前一个气球有边界,箭数加一
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) {
sort(points.begin(), points.end(), cmp);
int res = 1;
for(int i = 1; i < points.size(); i++){
if(points[i][0] > points[i-1][1]) //左边界大于前一个右边界
res++;
else{
points[i][1] = min(points[i-1][1], points[i][1]);//更新右边界
}
}
return res;
}
};