题目大意
Gas Station
解题思路
贪心法。但其实需要证明,证明详见:
http://bookshadow.com/weblog/2015/08/06/leetcode-gas-station/
看懂证明,才能看懂代码
结论1:若从加油站A出发,恰好无法到达加油站C(只能到达C的前一站)。则A与C之间的任何一个加油站B均无法到达C。
反证法:
假设从加油站A出发恰好无法到达加油站C,但是A与C之间存在加油站B,从B出发可以到达C。
而又因为从A出发可以到达B,所以A到B的油量收益(储油量 - 耗油量)为正值,进而可以到达C。
推出矛盾,假设不成立。
换一种理解方式:
如果到中间的某个位置, 剩余的油量为负了, 那么说明之前累积剩下的油量不够从这一站到下一站了. 那么就从下一站从新开始计数. 为什么是下一站, 而不是之前的某站呢? 因为第一站剩余的油量肯定是大于等于0的, 然而到当前一站油量变负了, 说明从第一站之后开始的话到当前油量只会更少而不会增加. 也就是说从第一站之后, 当前站之前的某站出发到当前站剩余的油量是不可能大于0的. 所以只能从下一站重新出发开始计算从下一站开始剩余的油量, 并且把之前欠下的油量也累加起来, 看到最后剩余的油量是不是大于欠下的油量.
结论2:若储油量总和sum(gas) >= 耗油量总和sum(cost),则问题一定有解。
代码
Python
class Solution: # @param {integer[]} gas # @param {integer[]} cost # @return {integer} def canCompleteCircuit(self, gas, cost): start = sums = 0 for x in range(len(gas)): sums += gas[x] - cost[x] if sums < 0: start, sums = x + 1, 0 return start if sum(gas) >= sum(cost) else -1
class Solution(object): def canCompleteCircuit(self, gas, cost): """ :type gas: List[int] :type cost: List[int] :rtype: int """ if sum(gas) < sum(cost): return -1 min_sum, min_index, total = 0, 0, 0 for i in range(len(gas)): print '----' total += gas[i] - cost[i] if min_sum > total: print 'gg' min_sum = total min_index = i + 1 print i, 'total:', total, 'min_sum:', min_sum, 'min_index:', min_index if total < 0: return -1 else: return min_index
Java
class Solution { public int canCompleteCircuit(int[] gas, int[] cost) { int n = gas.length; int total_tank = 0; int curr_tank = 0; int starting_station = 0; for (int i = 0; i < n; ++i) { total_tank += gas[i] - cost[i]; curr_tank += gas[i] - cost[i]; // If one couldn't get here, if (curr_tank < 0) { // Pick up the next station as the starting one. starting_station = i + 1; // Start with an empty tank. curr_tank = 0; } } return total_tank >= 0 ? starting_station : -1; } }
总结