Leetcode:134. 加油站

[Leetcode: 134. 加油站]

题目描述

在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升。

你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。

如果你可以绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1。

说明:

如果题目有解,该答案即为唯一答案。
输入数组均为非空数组,且长度相同。
输入数组中的元素均为非负数。

示例 1:

输入: 
gas  = [1,2,3,4,5]
cost = [3,4,5,1,2]

输出: 3

解释:
从 3 号加油站(索引为 3 处)出发,可获得 4 升汽油。此时油箱有 = 0 + 4 = 4 升汽油
开往 4 号加油站,此时油箱有 4 - 1 + 5 = 8 升汽油
开往 0 号加油站,此时油箱有 8 - 2 + 1 = 7 升汽油
开往 1 号加油站,此时油箱有 7 - 3 + 2 = 6 升汽油
开往 2 号加油站,此时油箱有 6 - 4 + 3 = 5 升汽油
开往 3 号加油站,你需要消耗 5 升汽油,正好足够你返回到 3 号加油站。
因此,3 可为起始索引。

示例 2:

输入: 
gas  = [2,3,4]
cost = [3,4,3]

输出: -1

解释:
你不能从 0 号或 1 号加油站出发,因为没有足够的汽油可以让你行驶到下一个加油站。
我们从 2 号加油站出发,可以获得 4 升汽油。 此时油箱有 = 0 + 4 = 4 升汽油
开往 0 号加油站,此时油箱有 4 - 3 + 2 = 3 升汽油
开往 1 号加油站,此时油箱有 3 - 3 + 3 = 3 升汽油
你无法返回 2 号加油站,因为返程需要消耗 4 升汽油,但是你的油箱只有 3 升汽油。
因此,无论怎样,你都不可能绕环路行驶一周。

[思路]

思路1 暴力判断每个位置是否可以作为起点

直接判断每个位置是否可以作为起点

思路2 利用当前油量和总油量记录状态

使用cur_gas和gas_sum记录当前油量和总油量,当当前油量小于零时则该位置不可作为起点,且之前节点也不行,依次类推,详情见代码

代码

代码1

class Solution {
    public int canCompleteCircuit(int[] gas, int[] cost) {
        if (gas == null || gas.length == 0 || cost == null || cost.length == 0 || gas.length != cost.length){
            return -1;
        }
        int length = gas.length;
        Set notZeroSet = new HashSet<>();
        for(int i = 0; i < gas.length; i++){
            gas[i] = gas[i] - cost[i];
            if (gas[i] >= 0){
                notZeroSet.add(i);
            }
        }
        for(int num: notZeroSet){
            if (canLoop(num, gas, length)){
                return num;
            }
        }
        return -1;
    }
    
    private boolean canLoop(int num, int[] lefts, int length){
        int left = lefts[num];
        for(int i = 1; i < length; i++){
            left = left + lefts[(i + num) % length];
            if (left < 0){
                return false;
            }
        }
        return true;
    }
}

代码2

class Solution {
    public int canCompleteCircuit(int[] gas, int[] cost) {
        if (gas == null || gas.length == 0 || cost == null || cost.length == 0 || gas.length != cost.length){
            return -1;
        }
        
        
        int cur_gas = 0;
        int gas_sum = 0;
        int result = 0;
        for(int i = 0; i < gas.length; i ++){
            cur_gas += gas[i] - cost[i];
            gas_sum += gas[i] - cost[i];
            if (cur_gas < 0){
                result = i + 1;
                cur_gas = 0;
            }
        }
        return gas_sum >= 0 ? result : -1;
    }
}

复杂度分析

思路1时间复杂度

$O(n^2)$

思路1空间复杂度

$O(1)$

思路2时间复杂度


文章作者: 小风雷
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 小风雷 !
评论
 上一篇
Leetcode:146. LRU缓存机制 Leetcode:146. LRU缓存机制
Leetcode:146. LRU缓存机制题目描述运用你所掌握的数据结构,设计和实现一个  LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 get 和 写入数据 put 。 获取数据 get(key) - 如果密钥 (k
2020-05-14
下一篇 
Leetcode:371. 两整数之和 Leetcode:371. 两整数之和
[Leetcode: 371. 两整数之和]题目描述不使用运算符 + 和 - ​​​​​​​,计算两整数 ​​​​​​​a 、b ​​​​​​​之和。 示例 1:输入: a = 1, b = 2 输出: 3 示例 2:输入: a = -
2020-05-08
  目录