算法学习day29-贪心算法

加油站

核心思路

  • 思路1, 全局

    • 如果能跑完全程, 那么加油站的油的总和一定是大于cost的总和的

    • 能跑完全程的前提下, 找到欠油的min, 从后往前执行, 找到能把min填平的下标, 就是起点

    • 这个逻辑还是有点难理解, 二刷的时候再捋一下吧

      java 复制代码
      public int canCompleteCircuit(int[] gas, int[] cost) {
          int curLast = 0;
          int min = 0;
          for (int i = 0; i < gas.length; i++) {
              curLast += gas[i] - cost[i];
              min = Math.min(min, curLast);
          }
          //说明加油站的油不足以支撑跑完全程
          if(curLast < 0){
              return -1;
          }
          //说明从0出发就能够跑完全程
          if(min >= 0){
              return 0;
          }
          //倒着执行, min说明这条路从0到结束最多欠了多少油
          //从后往前执行, 找到能填满min的位置, 就是起始位
          for (int i = gas.length - 1; i >= 0 ; i--) {
              min += gas[i] - cost[i];
              if(min >= 0){
                  return i;
              }
          }
          return -1;
      }
  • 思路2, 贪心

    • 首先确保 加油站的油的总和一定是大于cost的总和

    • 在这个前提下, 从0出发, 计算每个下标的剩余油量, 如果出现 负的, 那么就从i+1重新出发

    • 那么最终的结果, 要么totalCost<0, return -1

    • 要么出现一个index, 能够跑完全程

      java 复制代码
      public int canCompleteCircuit(int[] gas, int[] cost) {
          int totalCost = 0;
          int curLast = 0;
          int beginIndex = 0;
          for (int i = 0; i < gas.length; i++) {
              curLast += gas[i] - cost[i];
              totalCost += gas[i] - cost[i];
              if (curLast < 0) {
                  curLast = 0;
                  beginIndex = (i + 1) % gas.length;
              }
          }
          if(totalCost < 0){
              return -1;
          }
          return beginIndex;
      }

分发糖果

核心思路

  • 分成两次循环, 分别判断大于左孩子和大于右孩子

  • 需要注意的是, 判断左孩子, 要从前向后, 因为每次计算糖果的时候, 都要用到左孩子的值, 如果从后向前, 左孩子的值还没有更新

  • 右孩子同理, 要从后向前

    java 复制代码
    public int candy(int[] ratings) {
        int[] candy = new int[ratings.length];
        Arrays.fill(candy, 1);
        for (int i = 1; i < ratings.length; i++) {
            if (ratings[i] > ratings[i - 1]) {
                candy[i] = Math.max(candy[i - 1] + 1, candy[i]);
            }
        }
        for (int i = ratings.length - 2; i >= 0; i--) {
            if (ratings[i] > ratings[i + 1]) {
                candy[i] = Math.max(candy[i + 1] + 1, candy[i]);
            }
        }
        return IntStream.of(candy).sum();
    }

卖柠檬水

  • 这道题就单纯的考思路了

    • 5元的不用处理,

    • 10元的只能找5元的, 所以ten++, five--

    • 20元的, 既可以ten--,five--. 也可以five-=3

      • 那么这时候就要贪心一下, 优先ten--, 因为10元只能用于找零20块的, 所以尽可能的消耗10元
      java 复制代码
      public boolean lemonadeChange(int[] bills) {
          int five = 0;
          int ten = 0;
          for (int bill : bills) {
              if (bill == 5) {
                  five++;
              } else if (bill == 10) {
                  ten++;
                  five--;
              } else {
                  if (ten > 0) {
                      ten--;
                      five--;
                  } else {
                      five -= 3;
                  }
              }
              if (five < 0) {
                  return false;
              }
          }
          return true;
      }

根据身高重建队列

核心思路

  • 当有多个维度的时候, 要考虑能不能一个维度一个维度的分开处理

  • 这道题有两个维度, 一个是身高h, 一个是顺序k

    • 如果先根据k排序, 那么h会影响到k的排序效果, 所以先处理k不行
    • 如果先根据身高排序
      • 先处理高个子之后, 矮个子无论插入到哪个位置, 都不会影响到高个子的相对位置
      • 高个子看不见矮个子
    • 根据身高排序之后
      • 再顺序遍历, 将person[i] 插入到list的person[i][1]中, 就会发现
      • 由于先插入的是高个子, 矮个子即使插入到高个子前面, 也不会影响到高个子的相对位置!
    java 复制代码
    public int[][] reconstructQueue(int[][] people) {
        Arrays.sort(people, (a, b) -> {
            if (a[0] == b[0]) {
                return a[1] - b[1];
            }
            return b[0] - a[0];
        });
        ArrayList<int[]> list = new ArrayList<>();
        for (int[] person : people) {
            list.add(person[1], person);
        }
        return list.toArray(new int[people.length][]);
    }
相关推荐
草履虫建模10 小时前
力扣算法 1768. 交替合并字符串
java·开发语言·算法·leetcode·职场和发展·idea·基础
naruto_lnq12 小时前
分布式系统安全通信
开发语言·c++·算法
Jasmine_llq12 小时前
《P3157 [CQOI2011] 动态逆序对》
算法·cdq 分治·动态问题静态化+双向偏序统计·树状数组(高效统计元素大小关系·排序算法(预处理偏序和时间戳)·前缀和(合并单个贡献为总逆序对·动态问题静态化
ASKED_201913 小时前
Langchain学习笔记一 -基础模块以及架构概览
笔记·学习·langchain
爱吃rabbit的mq13 小时前
第09章:随机森林:集成学习的威力
算法·随机森林·集成学习
(❁´◡`❁)Jimmy(❁´◡`❁)13 小时前
Exgcd 学习笔记
笔记·学习·算法
YYuCChi14 小时前
代码随想录算法训练营第三十七天 | 52.携带研究材料(卡码网)、518.零钱兑换||、377.组合总和IV、57.爬楼梯(卡码网)
算法·动态规划
不能隔夜的咖喱14 小时前
牛客网刷题(2)
java·开发语言·算法
VT.馒头14 小时前
【力扣】2721. 并行执行异步函数
前端·javascript·算法·leetcode·typescript
进击的小头14 小时前
实战案例:51单片机低功耗场景下的简易滤波实现
c语言·单片机·算法·51单片机