在一条环路上有 n 个加油站,其中第 i 个加油站有 gas[i] 升油,假设汽车油箱容量无限,从第 i 个加油站驶往第 (i+1)%n 个加油站需要花费 cost[i] 升油。
请问能否绕环路行驶一周,如果可以则返回出发的加油站编号,如果不能,则返回 -1。
题目数据可以保证最多有一个答案。
数据范围: , gas 和 cost 数组中的值满足
[1,2,3,4,5],[3,4,5,1,2]
3
只能从下标为 3 的加油站开始完成 (即第四个加油站)
[0,10],[9,1]
1
[2,3,4],[3,4,5]
-1
无论从哪个加油站出发都无法环绕环道一圈
import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param gas int整型一维数组 * @param cost int整型一维数组 * @return int整型 */ public int gasStation (int[] gas, int[] cost) { // write code here LinkedList<Integer> candicates = new LinkedList<>(); int n = gas.length; for(int i = 0; i < n; i++){ gas[i] -= cost[i]; if(gas[i] >= 0){ candicates.add(i); } } while(!candicates.isEmpty()){ int startPoint = gameStarted(gas, candicates.removeFirst()); if(startPoint != -1){ return startPoint; } } return -1; } private int gameStarted(int[] energy, int start) { int cur = start; int cumsum = energy[cur]; cur++; if(cur == energy.length) cur = 0; while(cur != start){ if(cumsum >= 0){ cumsum += energy[cur]; cur++; if(cur == energy.length) cur = 0; }else{ return -1; // 累加一圈出现了负数 } } return start; } }
解题思路:挨个检查是否满足gas[i] - cost[i] >= 0 如果满足,则说明该加油站有充足的油驶往下一个加油站,则开始模拟加油过程。时间复杂度o(n^2).
import java.util.*; public class Solution { public int gasStation (int[] gas, int[] cost) { int res = 0; for(int i = 0; i < gas.length; ++i) { if(gas[i] < cost[i]) continue; res = gas[i]; for(int j = 0; j < gas.length; ++j) { res -= cost[(j + i) % gas.length]; if(res < 0) break; res += gas[(j + i + 1) % gas.length]; } if(res >= 0) return i; } return -1; } }
static const auto io_sync_off = [](){ std::ios::sync_with_stdio(false); std::cout.tie(nullptr); std::cin.tie(nullptr); return nullptr; }(); class Solution { public: int gasStation(vector<int>& gas, vector<int>& cost) { int curSum=0; int min=INT_MAX; for(int i=0;i<gas.size();i++) { int rest=gas[i]-cost[i]; curSum+=rest; if(curSum<min) min=curSum; } if(curSum<0) return -1; if(min>=0) return 0; for(int i=gas.size()-1;i>=0;i--) { int rest=gas[i]-cost[i]; min+=rest; if(min>=0) return i; } return -1; } };
import java.util.*; // 这个题, 和简单题,求子序列的最大和,有点像 public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param gas int整型一维数组 * @param cost int整型一维数组 * @return int整型 */ public int gasStation (int[] gas, int[] cost) { // write code here // *) int s = 0; int sum = 0; int n = gas.length; for (int i = 0; i < n; i++) { int delta = gas[i] - cost[i]; sum += delta; // 维护子序列的和 >= 0, 移动子序列的头指针 while (sum < 0 && s <= i) { sum -= (gas[s] - cost[s]); s++; } } // 补剩下的环 for (int i = 0; i < s; i++) { sum += (gas[i] - cost[i]); } if (sum >= 0) { return s; } return -1; } }
import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param gas int整型一维数组 * @param cost int整型一维数组 * @return int整型 */ public int gasStation (int[] gas, int[] cost) { int spare=0; int minspare=Integer.MAX_VALUE; int index=0; for(int i=0;i<gas.length;i++){ spare+=gas[i]-cost[i]; if(spare<minspare){ minspare=spare; index=i; } } return spare>=0?index+1:-1; // write code here } }
import java.util.*; public class Solution { public int gasStation (int[] gas, int[] cost) { // write code here int gasCapacity = 0; int begin = -1; for (;;) { begin++; if (begin == gas.length) return -1; //走完一圈没有发现有站点满足需求 返回-1 for (int i = begin; i < begin + gas.length; i++) { gasCapacity += gas[i % gas.length]; //膜一下,当超出范围会回到起点 gasCapacity -= cost[i % gas.length]; if (gasCapacity < 0) { //当前站点累计的汽油不足以到下一个站点 gasCapacity = 0; break; } if (i == begin + gas.length - 1) { //判断是否已经走了一圈,返回这个初始站点的位置 return begin; } } } } }