题目大意
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;
}
}