871. 最低加油次数

想象成不是只在加油站才能加油,而是只要现在需要油,并且之前有加油站还没有用,那么此时就可以加油。这样一来,如果要使得加油次数最少,那么只要加油就加最多的油,为了保证时间效率,这里用堆来维护前面的未用过的加油站里的油量。需要加油而没有油时(也就是堆为空),那么就不能够到达,此时返回-1。
这一题就是贪心+优先队列。

  1. class Solution {
  2. public static int minRefuelStops(int target, int startFuel, int[][] stations) {
  3. if (target <= startFuel) return 0;
  4. if (stations.length == 0 && target > startFuel) return -1;
  5. PriorityQueue<Integer> queue = new PriorityQueue<Integer>((o1, o2) -> (o2 - o1));
  6. int maxPosition = startFuel;
  7. int count = 0;
  8. for (int i = 0; i < stations.length; i++) {
  9. while (maxPosition < stations[i][0]) {
  10. if (queue.isEmpty()) return -1;
  11. maxPosition += queue.poll();
  12. count++;
  13. }
  14. queue.offer(stations[i][1]);
  15. }
  16. while (maxPosition < target) {
  17. if (queue.isEmpty()) return -1;
  18. maxPosition += queue.poll();
  19. count++;
  20. }
  21. return count;
  22. }
  23. }

如果加油站没有排过序,需要排序下,可以按照距离升序+油量降序

  1. Arrays.sort(stations, new Comparator<int[]>() {
  2. @Override
  3. public int compare(int[] o1, int[] o2) {
  4. if (o1[0] == o2[0]) return o2[1] - o1[1];
  5. else return o1[0] - o2[0];
  6. }
  7. });

134. 加油站

下面第20行,如果是写成i++,效率会低很多
假设从编号为0站开始,一直到k站都正常,在开往k+1站时车子没油了。这时,应该将起点设置为k+1站。

  1. class Solution {
  2. public int canCompleteCircuit(int[] gas, int[] cost) {
  3. int n = gas.length;
  4. int i = 0;
  5. while (i < n) {
  6. int sumOfGas = 0, sumOfCost = 0;
  7. int cnt = 0;
  8. while (cnt < n) {
  9. int j = (i + cnt) % n;
  10. sumOfGas += gas[j];
  11. sumOfCost += cost[j];
  12. if (sumOfCost > sumOfGas) {
  13. break;
  14. }
  15. cnt++;
  16. }
  17. if (cnt == n) {
  18. return i;
  19. } else {
  20. i = i + cnt + 1; // 超级巧妙的一步
  21. }
  22. }
  23. return -1;
  24. }
  25. }