代码随想录算法训练营Day35|860.柠檬水找零、406.根据身高重建队列、452. 用最少数量的箭引爆气球

目录

860.柠檬水找零

前言

思路

算法实现

406.根据身高重建队列

 前言

思路

算法实现

452. 用最少数量的箭引爆气球

前言

思路

算法实现

总结


860.柠檬水找零

题目链接

文章链接

前言

        本题要判断是否能实现对每位顾客正确找零,一共有5元、10元、20元三种面值的钞票,每杯柠檬水的售价是固定的5美元。只要每次交易后对三种面值的钞票进行准确的变化统计即可判断是否能够正确找零。

思路

         对于三种不同面值的钞票,有如下处理措施:

  • 对于5元钞票,直接收入,将num5++;
  • 对于10元钞票,要返回5元,记为num10++,num5--;
  • 对于20元钞票,有两种返现处理方案,第一种返回10+5(num10--,num5--),第二种则返回5+5+5(num5 += 3)。

        对于20元钞票的处理,由于返现无法使用出去,因此不需要记录num20,对于两种返现方案,利用贪心的思想优先采用第一种,因为5元钞票的使用范围更广。

算法实现

class Solution {
public:
    bool lemonadeChange(vector<int>& bills) {
        if (bills[0] != 5) return false;
        int sum = 0;
        // 20美元无法用于找零,因此不用设用于计数的变量
        int num_5 = 0;
        int num_10 = 0;
        for (int i = 0; i < bills.size(); i++){
            // 利用净交易值初步判断能否找零
            if (sum < bills[i] - 5) return false;
            // 进一步判断
            if (bills[i] == 5) num_5++;
            else if (bills[i] == 10) {
                num_5--;
                num_10++;
            }
            else { // 20美元的找零方式有两种:10 + 5 和 3 * 5
               if (num_10 > 0){
                    num_5--;
                    num_10--;
               }
               else num_5 -= 3;
            }
            if (num_5 < 0 || num_10 < 0) return false;

            sum += 5;
        }
        return true;
    }
};

406.根据身高重建队列

题目链接

文章链接

 前言

        本题与昨天分发糖果的题目有些类似,也要考虑两个维度,h和k,依旧是要先想如何确定一个维度,然后再按照另一个维度重新排列。

思路

         首先要考虑的是先按哪个维度进行排列,如果按照个数k来排,会发现k的排列并不符合条件,身高也不符合条件,两个维度哪一个都没确定下来。如果按照身高h来排,高个子的一定排在前面。

        此时我们可以确定一个维度了,就是身高,前面的节点一定都比本节点高!按照身高排序之后,优先按身高高的people的k来插入,后序插入节点也不会影响前面已经插入的节点,最终按照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);
        list<vector<int>> que;
        for (int i = 0; i < people.size(); i++){
            int position = people[i][1];
            std::list<vector<int>>::iterator it = que.begin();
            while (position--){
                it++;
            }
            que.insert(it, people[i]);
        }
        return vector<vector<int>>(que.begin(), que.end());
    }
};

452. 用最少数量的箭引爆气球

题目链接

文章链接

前言

        本题的难点在于如何让判断多个气球能否同时被一箭引爆。

思路

         为了让气球尽可能的重叠,需要对数组进行排序,本题采用以气球起始位置排序进行排序。如果气球重叠了,重叠气球中右边边界的最小值 之前的区间一定需要一个弓箭

算法实现

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 num = 1;
        for (int i = 1; i < points.size(); i++){
            if (points[i][0] > points[i - 1][1]) num++;
            else {
                points[i][1] = min(points[i - 1][1], points[i][1]);
            }
        }
        return num;
    }
};

        本算法的巧妙之处在于发现重合气球后,动态更新数组右边界,再对下一个数组进行重合判断。

总结

        今天的第一题难度不大,自己直接实现,第二题复习了一下对于两个维度的问题的处理方式,以及第三题初步认识了重叠区间问题的处理方法。

  • 16
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值