LeetCode 134 - gas station

【思路】

加油问题,暴力不可取( O(n^2) ),建议采用线性算法,无额外空间占用,只要998,只要998大笑

我们举个栗子

gas = [7, 5, 6, 0, 6]

cost = [3, 0, 0, 18, 2]

对应求差得到

dec = [7-3, 5-0, 6-0, 0-18, 6-2] = [4, 5, 6, -18, 4]


那么我们按照dec这个列表从头到尾遍历一遍,油量初始化为0

i = 0, dec[i] = 4

油量 = 0+4 = 4

i = 1, dec[i] = 5

油量 = 4+5 = 9

i = 2, dec[i] = 6

油量 = 9+6 = 15

i = 3, dec[i] = -18

油量 = 15-18 = -3 (这里允许负数, 为了方便后面分析)

i = 4, dec[i] = 4

油量 = -3+4 = 1

我们可以得到一个油量表 = [4, 9, 15, -3, 1],从这个表中我们可以获取到关键信息:


1. gas和cost列表各自求和,gas总和如果大于等于cost总和,说明可以找到这样一个起始点,使得环绕路线成为可能,否则找不到起始点

那么油量表中的最后一个数值就代表了gas总和与cost总和的差值,就可以判断了

例子中,最后一个是1,说明这样的起点是存在的


2. 油量表在最低值时,如果从这个最低值的下一刻开始出发,能够让油量表的每个值尽量大,比如以i = 4为起点,油量初始化为0, 那么

i = 4, dec[i] = 4

油量 = 0+4 = 4

i = 0, dec[i] = 4

油量 = 4+4 = 8

i = 1, dec[i] = 5

油量 = 8+5 = 13

i = 2, dec[i] = 6

油量 = 13+6 = 19

i = 3, dec[i] = -18

油量 = 19-18 = 1

油量表 = [8, 13, 19, 1, 4]

说明要找到符合条件的起点,只需要在原来的油量表中找到最后一个最小值(如果有多个的话)的位置,再求该位置的下一个即可,如果已经是最后一个,就返回表头位置

例子中,最小值为-3,下标为i = 3,求得起始下标4


【代码】

class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        int size = gas.size();

        int curgas = 0; // 汽车当前油量
        int mingas; // 汽车出现过的最小油量
        int res = -1;
        
        // 计算差值,累加到当前油量上,求最小油量(可以为负数)的下标,则下一个坐标就可以作为起点
        for (int i=0; i<size; i++) {
            curgas += gas[i]-cost[i];
            if (res == -1 || mingas >= curgas) { // 求最后一个最小值的下标
                mingas = curgas;
                res = i;
            }
        }
        
        return (curgas >= 0)? (res+1)%size : -1;
    }
};


©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页