算法随想Day31【贪心算法】| LC860-柠檬水找零、LC406-根据身高重建队列、LC452-用最少数量的箭引爆气球

LC860. 柠檬水找零

bool lemonadeChange(vector<int>& bills)
{
    int C5 = 0, C10 = 0;
    for (int i = 0; i < bills.size(); ++i)
    {
        if (bills[i] == 5)
        {
            ++C5;
        }
        else if(bills[i] == 10)
        {
            --C5;
            ++C10;
        }
        else if (bills[i] == 20)
        {
            if (C10 >= 1)
            {
                --C10;
                --C5;
            }
            else
                C5 = C5 - 3;
        }
        if (C5 < 0)
        {
            return false;
        }
    }

    return true;
}

LC406. 根据身高重建队列

有点像找规律的味道了,不禁赞叹出题人的精妙和过人之处。

这道题关键在于,先按照身高降序,同时排位升序的规则对原数组排好序,然后逐个插入,要插入result结果数组的位置已经在当前要插入元素的排位中标明白了。

  • 遇到两个维度权衡的时候,一定要先确定一个维度,再确定另一个维度。(参考分发糖果 -- 做不到同时兼顾左规则和右规则,所以需要分开两者,分别处理一遍)
  • 两个维度一起考虑一定会顾此失彼
static bool cmp(vector<int>& v1, vector<int>& v2)
{
    return ((v1[0] == v2[0]) && (v1[1] <= v2[1]) || (v1[0] > v2[0]));
}
vector<vector<int>> reconstructQueue(vector<vector<int>>& people)
{
    vector<vector<int>> result;
    sort(people.begin(), people.end(), cmp);
    result.emplace_back(people[0]);
    for (int i = 1; i < people.size(); ++i)
    {
        // if (people[i][0] == people[i - 1][0])
        // {
        //     result.emplace(people.begin() + i);
        // }
        result.emplace(result.begin() + people[i][1], people[i]);
    }
    return result;
}

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

我的想法是,排序后(先左边界升序,再右边界升序),遍历每个气球的范围,若与前一个有相交范围,则说明不用增加箭,只需更新公共范围。如遇下一个气球不在该公共范围内,则必须加1条箭,然后更新公共范围为该气球的范围。

如下注释掉了,是后来优化的:其实对左边界排序,然后每次循环维护右边界right就行。

static bool cmp(vector<int>& v1, vector<int>& v2)
{
    //return ((v1[0] == v2[0]) && (v1[1] <= v2[1]) || (v1[0] < v2[0]));
    return (v1[0] < v2[0]);
}
int findMinArrowShots(vector<vector<int>>& points)
{
    sort(points.begin(), points.end(), cmp);
    //int left = points[0][0];
    int right = points[0][1];
    int arrow = 1;
    for (int i = 1; i < points.size(); ++i)
    {
        if (right >= points[i][0])
        {
            //left = points[i][0];
            right = min(right, points[i][1]);
        }
        else
        {
            ++arrow;
            //left = points[i][0];
            right = points[i][1];
        }
    }

    return arrow;
}

官方解法:

class Solution {
public:
    int findMinArrowShots(vector<vector<int>>& points) {
        if (points.empty()) {
            return 0;
        }
        sort(points.begin(), points.end(), [](const vector<int>& u, const vector<int>& v) {
            return u[1] < v[1];
        });
        int pos = points[0][1];
        int ans = 1;
        for (const vector<int>& balloon: points) {
            if (balloon[0] > pos) {
                pos = balloon[1];
                ++ans;
            }
        }
        return ans;
    }
};
posted @ 2023-03-06 08:57  冥紫将  阅读(12)  评论(0)    收藏  举报