问题如下:
有N个加油站组成一个环状头尾相接的路线,且每个下标为i的加油站总共能加gas[i]的汽油,当前加油站到下一加油站所花费的汽油为cost[i],请写出程序判断是否存在下标index使得当你从index加油站开始开车,在车的初始汽油为0的情况下按顺序走过所有其他加油站回到index加油站,如果存在输出index值,如果不存在输出-1.
解答:
大家其实很容易能想到一个O(n^2)复杂度的方法,即遍历每个加油站(数组元素),以元素i为起点,按顺序将所有元素i之后的gas和cost汇总,当循环一轮回到元素i还未出现总和<0的情况,则说明i为解,若不是则将i+1设置为新的起点,以此类推。
其实存在O(n)复杂度的方法,即遍历一次所有加油站即可。
1、显而易见,gas总和减去cost总和为正数的情况下就一定存在index解,我们的方法是基于这个命题的,我们先证明该命题是否为真,该命题逆否命题为:如果不存在解(即无解),则gas和cost的总和为负。无解可以换句话表述:不存在任何一个数i,从i开始gas[i]-cost[i]为正数,所以gas和cost总和为负数。命题得证。
2、gas总和减去cost总和为负数的情况下就不存在index解。
3、总数为正,即存在解的情况下,如果元素j到元素k总和为负,则在[j,k]范围外存在解。
程序如下:
/** * @param {number[]} gas * @param {number[]} cost * @return {number} */ var canCompleteCircuit = function(gas, cost) { var total_gas = 0; var current_gas = 0; var index = 0; for(var i=0;i<gas.length;i++){ total_gas += gas[i] - cost[i]; current_gas += gas[i] - cost[i]; if(current_gas < 0){ current_gas = 0; index = i+1; } } return total_gas<0?-1:index; };