代码随想录第35天 贪心算法P4

文章介绍了在解决LeetCode上的三道问题时,如何运用局部最优和全局最优的策略。分别是860.柠檬水找零,通过调整找零策略实现;406.根据身高重建队列,按身高和优先级排序重建;452.用最少数量的箭引爆气球,通过排序和迭代找到最少箭数。
摘要由CSDN通过智能技术生成

第一部分:860.柠檬水找零

1.1题目链接

力扣https://leetcode.cn/problems/lemonade-change/

1.2解题思路

我的思路:

分情况:顾客拿5元的直接收进来。拿10元的,用5元找零。拿20元的,首先找零5+10,或者直接找零三个5.

代码随想录思路:

所以局部最优:遇到账单20,优先消耗美元10,完成本次找零。全局最优:完成全部账单的找零。

局部最优可以推出全局最优。

1.3解题代码

class Solution {
public:
    bool lemonadeChange(vector<int>& bills) {
        int charge[2];
        for(int i = 0; i < bills.size(); i++){
            if(bills[i] == 5) charge[0] += 5;
            if(bills[i] == 10) {
                charge[0] -= 5;
                if(charge[0] < 0){
                    return false;
                }
                charge[1] += 10;
            }
            if(bills[i] == 20){
                charge[0] -= 5;
                if(charge[1] != 0) charge[1] -= 10;
                else charge[0] -= 10;
                if(charge[0] < 0 || charge[1] < 0){
                    return false;
                }
            }
        }
        return true;
    }
};

第二部分:406.根据身高重建队列

2.1题目链接

力扣https://leetcode.cn/problems/queue-reconstruction-by-height/

2.2解题思路

本题有两个维度,h和k,看到这个题一定要想到如何确定一个维度,
然后再按照另一个维度重新排序。

本题目先按照身高排序:

身高从大到小(身高相同的k小的站在前面)

 按照k值进行插入

按照身高排序之后,有限按身高高的人people的k来插入,后续插入节点也不会影响到前面已经插入的节点。

局部最优:优先按身高的people的k来插入。插入操作后的people满足队列的属性。
全局最优:最后都做完插入操作,这个队列满足题目队列属性。

2.3解题代码

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 position = people[i][1];
            que.insert(que.begin() + position, people[i]);
        }
        return que;
    }
};

第三部分:452.用最少数量的箭引爆气球

3.1题目链接

力扣https://leetcode.cn/problems/minimum-number-of-arrows-to-burst-balloons/

3.2解题思路

局部最优:当气球出现重叠,一起射,所用的弓箭最少。
全局最优:把所有的气球射爆所用的弓箭最小。

如何模拟气球射爆的过程?是在数组中移除元素还是做标记呢?

仔细思考如果把气球排序之后,从前遍历气球,被射过的气球仅仅跳过就行了,没有必要让气球移除。只要记录一下箭的数量就行。

为了尽可能让气球重叠,需要对数组进行排序。那么按照气球起始位置还是按照气球终止位置排序呢?

其实都可以,如果按照起始位置排序,那么就从前向后遍历气球数组。

从前向后遍历遇到重叠的气球了怎么办?

如果气球重叠了,重叠气球中右边边界的最小值之前的区域一定需要一个弓箭。

 3.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) {
        if(points.size() == 0)return 0;
        sort(points.begin(), points.end(),cmp);

        int result = 1;//points不为空,那么至少需要一只箭
        for(int i = 1; i < points.size(); i++){
            if(points[i][0] > points[i-1][1]){
                result++;//需要一只箭
            }
            else{
                points[i][1] = min(points[i-1][1], points[i][1]);//更新重叠气球的最小右边界
            }
        }
        return result;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值