【代码随想录第35天】 贪心4

860.柠檬水找零(简单)

LeetCode题目:860.柠檬水找零
代码随想录: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());
    }
};

vector和list的区别

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;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值