加油站
https://leetcode-cn.com/problems/gas-station/
画图法
我们需要判断这个环形数组中是否能够找到一个起点 start,使得从这个起点开始,gas 和 cost 的累加和一直大于等于 0。

可以看出其中有一段路 sum 小于 0 了,是不行的。如果把图像的最低点作为起点,就能让图像整体平移上去,保证了一直 大于等于 0。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
   | func canCompleteCircuit(gas []int, cost []int) int {     n := len(gas)     sum := 0     minSum := 0     start := 0
      for i := 0; i < n; i++ {         sum += gas[i] - cost[i]         if sum < minSum {             start = i + 1             minSum = sum         }     }
      if sum < 0 {         return -1     }          if start == n {         return 0     }     return start }
 
  | 
 
贪心法
基于以下结论:如果选择站点 i 作为起点「恰好」无法走到站点 j,那么 i 和 j 中间的任意站点 k 都不可能作为起点。
证明:因为如果恰好无法走到站点 j,则对于途中任意 i < k < j,油箱量 tank[k] 都要 > 0,而如果将 k 作为起点,则 tank[k] == 0,无法满足条件。
根据这个条件,我们可以一次遍历起点,从 0 开始,如果发现哪里走不动了,说明这个点以前的都不可能是起点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
   | func canCompleteCircuit(gas []int, cost []int) int {     n := len(gas)     sum, tank, start:= 0, 0, 0
      for i := 0; i < n; i++ {         sum += gas[i] - cost[i]         tank += gas[i] - cost[i]         if tank < 0 {                          tank = 0             start = i + 1         }     }
      if sum < 0 {         return -1     }
      if start == n {         return 0     }     return start }
 
  |