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 升汽油。
因此,无论怎样,你都不可能绕环路行驶一周。

解题

方法一:暴力

class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        for(int i=0;i<cost.size();i++){
            int rest=gas[i]-cost[i]; //初始的剩余油量
            int index=(i+1)%cost.size();
            while(rest>=0&&index!=i){
                rest+=gas[index]-cost[index];//剩余油量
                index=(index+1)%cost.size();
            }
            if(rest>=0&&index==i) return i;
        }
        return -1;
    }
};

方法二:使用图的思想来分析,时间复杂度 O(N),空间复杂度 O(1)。

柱状图

绿色:可添加的汽油 gas[i]

橙色:消耗的汽油 cost[i]

折线图

虚线(蓝色):当前加油站的可用值

实线(黑色):从0开始的总剩余汽油量

该方法的解释

  1. 首先判断总gas能不能大于等于总cost,如果总gas不够,一切都白搭对吧(总(gas- cost)不用单独去计算,和找最低点时一起计算即可,只遍历一次);
  2. 再就是找总(gas-cost)的最低点,不管正负(当然如果最低点都是正的话那肯定能跑完了);
  3. 找到最低点后,如果有解,那么解就是最低点的下一个点,因为总(gas-cost)是大于等于0的,所以前面损失的gas我从最低点下一个点开始都会拿回来!

总的来说,就是最低点损失的油量, 要从最低点的后面个点遍历道最低的点的前一个点,提供给最低点用(如果总油量大于总消耗,又题目已知存在唯一解,那么一定是成立的)。

class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        int l=gas.size();
        int spare=0;
        int minSpare=INT_MAX;
        int minIndex=0;
        for(int i=0;i<l;i++){
            spare+=gas[i]-cost[i];
            if(spare<minSpare){
                minSpare=spare;
                minIndex=i;
            }
        }
        if(spare<0) return -1;
        else return (minIndex+1)%l;
    }
};

更正后

class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        int curSum = 0;
        int totalSum = 0;
        int start = 0;
        for (int i = 0; i < gas.size(); i++) {
            curSum += gas[i] - cost[i];
            totalSum += gas[i] - cost[i];
            if (curSum < 0) {   // 当前累加rest[i]和 curSum一旦小于0
                start = i + 1;  // 起始位置更新为i+1
                curSum = 0;     // curSum从0开始
            }
        }
        if (totalSum < 0) return -1; // 说明怎么走都不可能跑一圈了
        return start;
    }
};

相关文章
|
3月前
|
算法 索引 Python
【Leetcode刷题Python】134. 加油站
LeetCode "加油站" 问题的Python实现代码,采用了一种优化的贪心算法。代码中通过两个指针i和j来模拟汽车的行驶过程,remain变量用来记录当前剩余油量。如果在某次循环中能够回到起始点i,则返回起始点索引;如果无法完成一圈,则移动到下一个可能的起始点继续尝试,直到找到可行的起始点或确定无法绕圈。如果整个过程结束后仍未找到解决方案,则返回-1。
32 0
|
5月前
|
算法 数据可视化 数据挖掘
最佳加油站选择算法:解决环路加油问题的两种高效方法|LeetCode力扣134
最佳加油站选择算法:解决环路加油问题的两种高效方法|LeetCode力扣134
|
6月前
|
索引
【力扣】134.加油站
【力扣】134.加油站
|
6月前
|
算法 vr&ar 图形学
☆打卡算法☆LeetCode 134. 加油站 算法解析
☆打卡算法☆LeetCode 134. 加油站 算法解析
|
算法 网络架构
代码随想录算法训练营第三十三天 | LeetCode 1005. K 次取反后最大化的数组和、134. 加油站、135. 分发糖果
代码随想录算法训练营第三十三天 | LeetCode 1005. K 次取反后最大化的数组和、134. 加油站、135. 分发糖果
55 0
|
算法
代码随想录Day28 贪心03 LeetCode T1005 K次取反后最大化的数组和 LeetCode T134 加油站 LeetCode T135 分发糖果
代码随想录Day28 贪心03 LeetCode T1005 K次取反后最大化的数组和 LeetCode T134 加油站 LeetCode T135 分发糖果
35 0
|
算法
leetcode 134 加油站
leetcode 134 加油站
55 0
leetcode 134 加油站
leetcode每日一题:134. 加油站
leetcode每日一题:134. 加油站
|
算法 Java 网络架构
加油站(LeetCode 134)
加油站(LeetCode 134)
98 0
|
算法 Java C++
代码随想录刷题|LeetCode 1005.K次取反后最大化的数组和 134. 加油站 135. 分发糖果
代码随想录刷题|LeetCode 1005.K次取反后最大化的数组和 134. 加油站 135. 分发糖果