力扣刷题-贪心算法1:

第一题:134. 加油站

  1. 题目说明
  2. 求解思路
    1)初始位置加的油要大于消耗的油
    2)如果最终加的油总和大于消耗油总和,那么一定存在某个出发点满足要求
  3. 求解步骤
    1)首先进行遍历,寻找总的获得与消耗的差值(为了后面判断是否存在唯一的出发点)
    2)在遍历上者时,对初始位置进行获得与消耗的积累,如果存在小于0,那么初始位置应该从下一个开始。(即通过排除法找到正确的位置,前提是正确位置存在)
    3)输出:如果正确位置存在,输出满足条件的start,如果不存在,输出为-1
  4. 代码展示
class Solution {
    public int canCompleteCircuit(int[] gas, int[] cost) {
        //1)初始位置加的油要大于消耗的油
        //2)如果最终加的油总和大于消耗油总和,那么一定存在某个出发点满足要求
        //3)通过对潜在出发点进行累计法,找到出发点
        int start=0;
        int runsum=0;
        int totalsum=0;
        //根据totalsum判断解是否存在
        //根据runsum判断满足条件start的位置所在
        for(int i=0;i<gas.length;i++){
            runsum+=gas[i]-cost[i];
            totalsum+=gas[i]-cost[i];
            if(runsum<0){
                start=i+1;
                runsum=0;
            }
        }
        return (totalsum>=0)?start:-1;
}
}
class Solution {
    //暴力解法超出时间限制(需要满足两个条件才能最终输出)
    public int canCompleteCircuit(int[] gas, int[] cost) {
        int start;
        for(start=gas.length-1;start>=0;start--){  //起始站点
            int sumgas=0;
            int sumcost=0;
            //第一种排除情况
            if(gas[start]<cost[start]) {
                continue;
            }
            //第二种排除情况
            for(int i=start;i<gas.length+start;i++){  //n次循环操作
                sumgas+=gas[i%gas.length];
                sumcost+=cost[i%gas.length];
                if(sumgas<sumcost){
                    break;
                }
            }
            if(sumgas<sumcost) continue;
            //符合两个条件才能输出
            return start;
        }
        return -1;

    }
}
  1. 补充说明
    1)也可以通过暴力进行求解,但是时间复杂度为O(n2),不一定能满足要求。
    2)这种问题像脑筋急转弯,要找到满足条件的东西。

第二题:135. 分发糖果

第三题:860.柠檬水找零

  1. 题目说明
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MG34tfZY-
  2. 求解思路
    根据题目要求,收上来的钱只能是5,10,20,故可以针对每一次收取与找零情况,进行判断。
  3. 求解步骤
    1)遍历收取上来的钱
    2)如果是5元,则five++; 如果是10元,则five–,ten++ ;如果是20元(优先five–,ten–,没有十元的,则five=five-3)
    3)每次找零之后判断手上钱是否都是正数,是负数则直接输出false,全部为正数,则输出true.
  4. 代码展示
class Solution {
    //依次找零,如果钱已经花出去了,那么就置-1
    public boolean lemonadeChange(int[] bills) {

        int num=0;
        int ling=0;
        for(int i=0;i<bills.length;i++){
            //此处需要对之前拿到的数据进行一个局部的排序,优先找零大的数!!!
            ling=bills[i]-5;
            //1)不需要找零
            if(ling==0)num++;
            //2)需要找零(在之前数中找)
            for(int j=i-1;j>=0;j--){
                if(bills[j]!=-1 && ling>=bills[j]){
                    ling-=bills[j];
                    bills[j]=-1;
                }
                if(ling==0){
                    num++;
                    break;
                }  
            }
            //3)找零后还有不等于0,则是错误
            if(ling>0) return false;
        }
        //如果能够遍历全部,那么就输出正确
        return true;
    }
}
//使用于手上来的钱不固定(代码没去全写完)
class Solution {
    //依次找零,如果钱已经花出去了,那么就置-1
    public boolean lemonadeChange(int[] bills) {

        int num=0;
        int ling=0;
        for(int i=0;i<bills.length;i++){
            //此处需要对之前拿到的数据进行一个局部的排序,优先找零大的数!!!
            Arrays.sort()   //注意:功能是对已经手上来钱的位置进行升序排列,代码没全写完
            ling=bills[i]-5;
            //1)不需要找零
            if(ling==0)num++;
            //2)需要找零(在之前数中找)
            for(int j=i-1;j>=0;j--){
                if(bills[j]!=-1 && ling>=bills[j]){
                    ling-=bills[j];
                    bills[j]=-1;
                }
                if(ling==0){
                    num++;
                    break;
                }  
            }
            //3)找零后还有不等于0,则是错误
            if(ling>0) return false;
        }
        //如果能够遍历全部,那么就输出正确
        return true;
    }
}
  1. 补充说明
    1)这道题变简单,因为收上来的钱种类是固定的。
    2)如果手上来的钱不是固定的,那么每次就需要优先把大钱找出去,
    3)这里就需要每次手上来的钱,需要进行一个排序,优先把大钱找出去,手上保留小钱。

第四题:406.根据身高重建队列

  1. 题目说明
  2. 求解步骤
    1)先重写数组的排序方法:先按第一个数的大小进行
  3. 代码展示
class Solution {
    public int[][] reconstructQueue(int[][] people) {
        //核心思路:思路非常巧妙。
        //1)把手上的数组按照第一个字符进行排序,然后依次存入到给定数组中去。
        //2)在存入过程中,按照第二个数进行排序(因为前面都是大的值,所以轮到某个数组,其第二个数暂时都是真实有效的)
        
        //1)首先对数据进行排序(比较第一个数大的再前面,相同大的,就比较第二个数,小的在前面)
        //重写sort方法
        Arrays.sort(people, (a,b) ->{
            if(a[0]==b[0]) return a[1]-b[1];
            return b[0]-a[0];
        });

        //2)把数据装载进去
        List<int[]> list=new ArrayList<>();

        //3)按照位序插入
        for(int i=0;i<people.length;i++){
            list.add(people[i][1],people[i]);
        }
        
        //4)输出为数组(集合转变为二维)(需要在转换的里面放入一个新建的二维数组)
        return list.toArray(new int[people.length][2]);
    }
}
  1. 补充说明
    1)第一处:就是对Arrays.sort()方法比较器部分的重写:先按第一个进行排倒序,如果第一个相等,则按第二个数排升序。
    2)在集合转为数组的时候,使用list.toArray(),括号里面新建一个所需的空数组。
    3)数组转变为集合:遍历方法,一次add添加。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值