算法学习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][]);
    }
相关推荐
编程小白20263 分钟前
从 C++ 基础到效率翻倍:Qt 开发环境搭建与Windows 神级快捷键指南
开发语言·c++·windows·qt·学习
学历真的很重要3 分钟前
【系统架构师】第二章 操作系统知识 - 第二部分:进程与线程(补充版)
学习·职场和发展·系统架构·系统架构师
qq7422349847 分钟前
APS系统与OR-Tools完全指南:智能排产与优化算法实战解析
人工智能·算法·工业·aps·排程
深蓝海拓12 分钟前
PySide6,QCoreApplication::aboutToQuit与QtQore.qAddPostRoutine:退出前后的清理工作
笔记·python·qt·学习·pyqt
酒鼎13 分钟前
学习笔记(3)HTML5新特性(第2章)
笔记·学习·html5
L***一28 分钟前
2026届大专跨境电商专业毕业生就业能力提升路径探析
学习
A尘埃33 分钟前
超市购物篮关联分析与货架优化(Apriori算法)
算法
.小墨迹40 分钟前
apollo学习之借道超车的速度规划
linux·c++·学习·算法·ubuntu
ZH15455891311 小时前
Flutter for OpenHarmony Python学习助手实战:模块与包管理的实现
python·学习·flutter
不穿格子的程序员1 小时前
从零开始刷算法——贪心篇1:跳跃游戏1 + 跳跃游戏2
算法·游戏·贪心