代码随想录-Day34~35-贪心算法-LetCode1860. 柠檬水找零||452. 用最少数量的箭引爆气球||435. 无重叠区间||56. 合并区间

860. 柠檬水找零

在柠檬水摊上,每一杯柠檬水的售价为 5 美元。顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯。

每位顾客只买一杯柠檬水,然后向你付 5 美元、10 美元或 20 美元。你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付 5 美元。

注意,一开始你手头没有任何零钱。

给你一个整数数组 bills ,其中 bills[i] 是第 i 位顾客付的账。如果你能给每位顾客正确找零,返回 true ,否则返回 false 。

        贪心思路:感觉也不算是贪心,就是常识,由于顾客只会支付 5元,10元,20元三种,于是我们可以分别用 five,ten来统计五元和十元的数量,然后根据用户的给钱成功找零即可

        

class Solution {
    public boolean lemonadeChange(int[] bills) {
        int ten=0;
        int five=0;
        for(int money:bills){
            if(money==5) {
                five++;
            }else if(money==10){
                if(five>0) {
                    five--;
                    ten++;
                }else{
                    return false;
                }
            }else {
                if(five>0&&ten>0){
                    ten--;
                    five--;
                }else if(five>=3){
                    five-=3;
                }else {
                    return false;
                }
            }
        }
        return true;
    }
}

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

有一些球形气球贴在一堵用 XY 平面表示的墙面上。墙面上的气球记录在整数数组 points ,其中points[i] = [xstart, xend] 表示水平直径在 xstart 和 xend之间的气球。你不知道气球的确切 y 坐标。

一支弓箭可以沿着 x 轴从不同点 完全垂直 地射出。在坐标 x 处射出一支箭,若有一个气球的直径的开始和结束坐标为 xstartxend, 且满足  xstart ≤ x ≤ xend,则该气球会被 引爆 。可以射出的弓箭的数量 没有限制 。 弓箭一旦被射出之后,可以无限地前进。

给你一个数组 points ,返回引爆所有气球所必须射出的 最小 弓箭数 

435. 无重叠区间

给定一个区间的集合 intervals ,其中 intervals[i] = [starti, endi] 。返回 需要移除区间的最小数量,使剩余区间互不重叠 

56. 合并区间

以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区

        贪心思路:个人感觉这三道题的思路是一致的,本质上来说都需要求解的都是是公用的区间,我们需要先让数组根据左边区间或者右边区间进行排序,完成之后在使用循环便利判断公共区间,就是用第二期个区间的左边界和第一个区间的右边界比较即可,有公共区间则需要更新右边界的值,最后统计即可。

        个人总结模版代码:

//将数组按照左区间进行排序
Arrays.sort(arr,(a,b)->Integer.compare(a[0],b[0]);
//遍历数组记录重合区间
for(int i=1;i<len;i++){
    if(arr[i][0]>arr[i-1][1]){
        //说明两个区间不重合,
    }else{
        //说明两个区间重合所以需要更新左右边界的值,方便下一次比较
        arr[i][1]=Math.min(arr[i][1],arr[i-1][1]);
    }
}

return **;

763. 划分字母区间

给你一个字符串 s 。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。

注意,划分结果需要满足:将所有划分结果按顺序连接,得到的字符串仍然是 s 。

返回一个表示每个字符串片段的长度的列表。

第一次看题目对他的意思不是很理解,先分析一下题目意思

s = "ababcbacadefegdehijhklij"

例如上述字符串,假如从第一个遍历,第一个是a,那么你需要保证a只能出现在一个片段中,直白得奖就是除了划分含有a的区间之外其他区间不能右a,也就是区间长度要达到a出现的最远位置,也及时这个题目中的8,同理继续便利到b,不也是一样的道理,只不过他比a小,于是我们取a,循环往复即可。

        说到这里之后,其实题目意思明白了,就很好求解,首先记录所有出现的字母最远的位置,一个for循环使用hash表就可以搞定,数组索引就是当前字母减去'a'。之后对字符数组进行遍历使用一个索引初始值为0-记录划分字符串的最有区间,每一次便利后和当前字母最远位置比较更新索引,当遍历到索引位置时,将切割的字符串加入结果集之中,重复上述操作即可。

        

class Solution {
    public List<Integer> partitionLabels(String s) {
        //先记录所有字母 的最远位置
        int[] maxindex=new int[26];
        for(int i=0;i<s.length();i++){
            char ch=s.charAt(i);
            maxindex[ch-'a']=i;
        }
        //使用right记录字幕的 最大右区间
        int right=0;
        //统计最终的结果
        List<Integer> res=new ArrayList<>();
        int count=0;
        for(int i=0;i<s.length();i++){
            right=Math.max(right,maxindex[s.charAt(i)-'a']);
            count++;
            if(i==right){
                res.add(count);
                count=0;
            }
            //count++;
        }
        return res;
    }
}

                                                                                                                               By-三体直线围墙

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值