加油站
核心思路
-
思路1, 全局
-
如果能跑完全程, 那么加油站的油的总和一定是大于cost的总和的
-
能跑完全程的前提下, 找到欠油的min, 从后往前执行, 找到能把min填平的下标, 就是起点
-
这个逻辑还是有点难理解, 二刷的时候再捋一下吧
javapublic 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, 能够跑完全程
javapublic 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; }
-
分发糖果
核心思路
-
分成两次循环, 分别判断大于左孩子和大于右孩子
-
需要注意的是, 判断左孩子, 要从前向后, 因为每次计算糖果的时候, 都要用到左孩子的值, 如果从后向前, 左孩子的值还没有更新
-
右孩子同理, 要从后向前
javapublic 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元
javapublic 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]中, 就会发现
- 由于先插入的是高个子, 矮个子即使插入到高个子前面, 也不会影响到高个子的相对位置!
javapublic 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][]); }