首页 > 其他分享 >(34/60)柠檬水找零、根据身高重建队列、用最少数量的箭引爆气球

(34/60)柠檬水找零、根据身高重建队列、用最少数量的箭引爆气球

时间:2024-03-05 18:24:46浏览次数:34  
标签:right 边界 people ++ 复杂度 找零 34 柠檬水 vector

柠檬水找零

leetcode:860. 柠檬水找零

贪心法

思路

遍历一遍数组,只关注面值5、10的钞票的数量

每轮判断:如果是5,five++;如果是10,判断还有没有5,有的话five--;如果是20,检查有没有一张10、一张5,ten--,five--。或者三张5,five-=3。

贪心:先消耗面值10的钞票,因为它更万能。

复杂度分析

时间复杂度:O(N)。

空间复杂度:O(1)。

注意点

代码实现

class Solution {
public:
    // 遍历bills,存储5、10的数量。
    // (10、20的时候检查钞票够不够)
    // 如果是5,存入、继续;如果是10,存入,5--,继续
    // 如果是20,10--,5--或者5-=3,继续
    bool lemonadeChange(vector<int>& bills) {
        int fiveNums = 0;
        int tenNums = 0;
        for(int i = 0;i < bills.size();i++){
            if(bills[i] == 5) fiveNums++;
            else if(bills[i] == 10){
                if(fiveNums > 0){
                    fiveNums--;
                    tenNums++;
                }else return false;
            }else if(bills[i] == 20){
                if(fiveNums > 0 && tenNums> 0){
                    fiveNums--;
                    tenNums--;
                }else if(fiveNums >= 3){
                    fiveNums -=3;
                }else return false;
            }
        }

        return true;
    }
};

根据身高重建队列

leetcode:406. 根据身高重建队列

贪心法

思路

复杂度分析

时间复杂度:

  • 对people数组进行排序的时间复杂度为O(n*log(n)),其中n为people的长度。
  • 在for循环中,每个人需要插入到list中,而插入操作的时间复杂度为O(n)(n为list的长度)。
  • 最后将list中的结果转换为vector需要O(n)的时间。

因此,总体来说,这段代码的时间复杂度为O(n^2 * log(n)),其中n为people的长度。

空间复杂度:取决于list空间占用,O(N)。

注意点

  1. (链表版)迭代器声明方式:

    container_type::iterator iterator_name;

  2. 迭代器不能直接进行加减运算,可以通过advance函数进行移动。(或者手写一个while循环让其自增自减)

  3. vector扩容的实质:在size超过capacity时,复制原值创建一个两倍capacity的新数组,摧毁旧数组。因此vector的insert操作不仅是遍历一遍的O(N),还有重建数组的O(N)。

代码实现

vector版:

class Solution {
public:
    // 先按身高倒序排序,然后根据第k插入相应位置
    static bool cmp(const vector<int>& a,const vector<int>& b){
        // 根据h从大到小排序
        if(a[0] == b[0]) return a[1] < b[1];    // 如果相等则按k升序
        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++) {
            que.insert(que.begin() + people[i][1],people[i]);
        }

        return que;
    }
};

链表版:

class Solution {
public:
    // 先按身高倒序排序,然后根据第k插入相应位置
    static bool cmp(const vector<int>& a,const vector<int>& b){
        // 根据h从大到小排序
        if(a[0] == b[0]) return a[1] < b[1];    // 如果相等则按k升序
        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++) {
            list<vector<int>>::iterator it = que.begin();
            advance(it,people[i][1]);
            que.insert(it,people[i]);
        }
        vector<vector<int>> result;
        for(vector<int> vec : que) result.push_back(vec);

        return result;
    }
};

用最少数量的箭引爆气球

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

贪心法

思路

  1. 按左边界从小到大排序,如果左边界相等,则按右边界从小到大排序。

    这步很关键,有了右边界和下一元素左、右边界比较已经不重要了)

  2. 遍历每个元素,arrow++,然后进行当前元素的边界的内检测:

    以当前元素为对比标准,取i的右边界为right

    若right >= i+1的左边界且right >= i+1右边界,那么一起射爆它,i++。

    若right < i+1右边界,那么right更改为i+1右边界,再i++(此时对比的标准已经转变为这个i+1元素)。

    直至不再满足这个条件。

    (关键在于,当前右边界与下一元素左、右边界都比较,如果right>左边界,可以一箭多雕;如果right>右边界,那么从right更新为下一元素的右边界,以下一元素为基准进行循环比较)

贪心:局部最优——每箭尽可能多射爆气球;总体最优——用尽可能少的箭射爆所有气球。

复杂度分析

时间复杂度:O(NlogN)。虽有两层循环,但只每个元素大致只遍历一次。复杂度主要在排序。

空间复杂度:O(1)。

注意点

代码实现

class Solution {
public:
    // 按左边界从小到大排序,如果左边界相等则按右边界从小到大排序。
    // 遍历每个元素,arrow++,然后进行当前元素的边界的内检测
    // 内检测:取i的右边界为right若right >= i+1的左边界且right >= i+1右边界,那么一起射爆它,i++,
    //                                      若right <  i+1右边界,那么right更改为i+1右边界
    // 直至不再满足这个条件
    static bool cmp(vector<int>& a,vector<int>& b){
        if(a[0] != b[0]) return a[0] < b[0];
        else return a[1] < b[1];
    }
    int findMinArrowShots(vector<vector<int>>& points) {
        sort(points.begin(),points.end(),cmp);
        int arrow = 0;
        for(int i = 0;i < points.size();i++){
            arrow++;
            int right = points[i][1];
            while(i < points.size() - 1 && right >= points[i + 1][0]){
                if(points[i + 1][1] < right) right = points[i + 1][1];
                i++;
            }
        }

        return arrow;
    }
};

标签:right,边界,people,++,复杂度,找零,34,柠檬水,vector
From: https://www.cnblogs.com/tazdingo/p/18054604

相关文章

  • 代码随想录算法训练营day13 | leetcode 239. 滑动窗口最大值、347. 前 K 个高频元素
    目录题目链接:239.滑动窗口最大值-困难题目链接:347.前K个高频元素-中等题目链接:239.滑动窗口最大值-困难题目描述:给你一个整数数组nums,有一个大小为k的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的k个数字。滑动窗口每次只向右移动一位。......
  • 34理解虚基类和虚继承
    理解虚基类和虚继承抽象类:有纯虚函数的类。而虚基类是被虚继承的类。classB:virtualpublicA如果是普通继承,B对象内存开头存储基类A的成员,后接B的独有成员。虚继承后B对象内存开头存储一个vbptr(virtualbaseptr),指向一个vbtable,vbtable存储两个偏移量,第一个偏移量是vbptr......
  • abc343比赛总结
    写在前面A简单,随便取两个值判一下,不过这道题的名字不吉利,叫什么WA啊?B简单,读入的时候判断一下是不是\(1\)就行了。C有点点难,题目不是那么好理解(尤其是英文不好的话)。虽然说\(N\le10^{18}\)但是仔细算一下其实只需要1e6的遍历一遍就够了,毕竟有个三次方。D......
  • 高级口译教程第5版pdf电子版,12341243
         1231123131231231第1篇:高级口译教程第四版UniteOne外事接待口译课文01浏览:2511第2篇:高级口译教程第四版UniteOne外事接待口译课文02浏览:1559第3篇:高级口译教程第四版UniteOne外事接待课外练习01浏览:1327第4篇:高级口译教程第四版Unite......
  • abc343G 题解
    题意给你\(N\)个由小写字母组成的字符串\(S_1,S_2,\ldots,S_N\),找出一个母串使得它包含所有这些字符串作为它的子串,最小化该母串的长度并输出。\(1\leqN\leq20\),\(\sum|S_i|\leq2\times10^5\)(没错洛谷翻译就是我写的)思路首先如果有一个字符串被另一个字符串......
  • 代码随想录 第13天 | ● 239. 滑动窗口最大值 ● 347.前 K 个高频元素 ● 总结
    leetcode:239.滑动窗口最大值-力扣(LeetCode)思路:看了挺长时间才反应过来与暴力算法的区别。当遇到比上一个元素大的值时,将上一个元素剔除,小于时加入队列中,每次等于窗口长度时将顶端也就是最大值存起来classSolution{publicint[]maxSlidingWindow(int[]nums,intk)......
  • ABC343 A~E 解题报告
    A-WrongAnswer模拟题,只需要每次输出\(0\)到\(9\)内不等于\(a+b\)的值就行了。#include<bits/stdc++.h>usingnamespacestd;template<typenameT>Tread(Tx){Topt=1,sum=0;charch=getchar();while(!isdigit(ch)){if(ch=='-')opt=......
  • ABC343 G Compress Strings 题解
    QuestionABC343GCompressStrings给定\(N\)个字符串\(S_1,S_2,\cdots,S_N\)找到一个包含所有这些字符串作为子字符串的最小长度的字符串一个字符串\(S\)包含一个字符串\(T\)作为子字符串是指:如果\(T\)可以通过从\(S\)的开头删除零个或多个字符以及从末尾删除......
  • AtCoder Beginner Contest 343
    AtCoderBeginnerContest343比赛链接A-WrongAnswer思路简单的模拟,事实上我们需要注意一下当a和b都为0的情况Code#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongvoidsolve(){ inta,b; cin>>a>>b; intans=a+b; //cout<<a+b-1<<en......
  • AtCoder Beginner Contest 343
    基本情况前四题秒了,但是都有不够优雅的地方F知道是线段树,但是写不出来,极其绝望C-343C-343(atcoder.jp)更简洁的回文判断MyCodeboolcheck_p(i64x){std::strings(std::to_string(x));intn=sz(s);for(inti=0;i<n/2;i++){if......