首先如果总油量减去总消耗大于等于零那么一定可以跑完一圈,说明 各个站点的加油站 剩油量rest[i]相加一定是大于等于零的。
    每个加油站的剩余量rest[i]为gas[i] - cost[i]。
    i从0开始累加rest[i],和记为curSum,一旦curSum小于零,说明[0, i]区间都不能作为起始位置,起始位置从i+1算起,再从0计算curSum。
    如图: image.png
    那么为什么一旦[i,j] 区间和为负数,起始位置就可以是j+1呢,j+1后面就不会出现更大的负数?
    如果出现更大的负数,就是更新j,那么起始位置又变成新的j+1了。
    而且j之前出现了多少负数,j后面就会出现多少正数,因为耗油总和是大于零的(前提我们已经确定了一定可以跑完全程)。
    那么局部最优:当前累加rest[j]的和curSum一旦小于0,起始位置至少要是j+1,因为从j开始一定不行。全局最优:找到可以跑一圈的起始位置。
    局部最优可以推出全局最优,找不出反例,试试贪心!
    局部最优可以推出全局最优,找不出反例,试试贪心!

    1. //贪心法
    2. public int canCompleteCircuit2(int[] gas, int[] cost) {
    3. int curSum = 0;
    4. int totalSum = 0;
    5. int start = 0;
    6. for (int i = 0; i < gas.length; i++) {
    7. curSum += gas[i] - cost[i];
    8. totalSum += gas[i] - cost[i];
    9. if (curSum < 0) { // 当前累加rest[i]和 curSum一旦小于0
    10. start = i + 1; // 起始位置更新为i+1
    11. curSum = 0; // curSum从0开始
    12. }
    13. }
    14. if (totalSum < 0) {
    15. return -1;
    16. }
    17. return start;
    18. }