LeetCode Top Interview Questions 134. Gas Station (Java版; Medium)

welcome to my blog

LeetCode Top Interview Questions 134. Gas Station (Java版; Medium)

题目描述

There are N gas stations along a circular route, where the amount of gas at station i is gas[i].

You have a car with an unlimited gas tank and it costs cost[i] of gas to travel from station i to its next station (i+1). 
You begin the journey with an empty tank at one of the gas stations.

Return the starting gas station's index if you can travel around the circuit once in the clockwise direction, otherwise return -1.

Note:

If there exists a solution, it is guaranteed to be unique.
Both input arrays are non-empty and have the same length.
Each element in the input arrays is a non-negative integer.
Example 1:

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

Output: 3

Explanation:
Start at station 3 (index 3) and fill up with 4 unit of gas. Your tank = 0 + 4 = 4
Travel to station 4. Your tank = 4 - 1 + 5 = 8
Travel to station 0. Your tank = 8 - 2 + 1 = 7
Travel to station 1. Your tank = 7 - 3 + 2 = 6
Travel to station 2. Your tank = 6 - 4 + 3 = 5
Travel to station 3. The cost is 5. Your gas is just enough to travel back to station 3.
Therefore, return 3 as the starting index.
Example 2:

Input: 
gas  = [2,3,4]
cost = [3,4,3]

Output: -1

Explanation:
You can't start at station 0 or 1, as there is not enough gas to travel to the next station.
Let's start at station 2 and fill up with 4 unit of gas. Your tank = 0 + 4 = 4
Travel to station 0. Your tank = 4 - 3 + 2 = 3
Travel to station 1. Your tank = 3 - 3 + 3 = 3
You cannot travel back to station 2, as it requires 4 unit of gas but you only have 3.
Therefore, you can't travel around the circuit once no matter where you start.

第一次做; 借助了不完整的数学证明, 比如能从a走到b-1, 但走不到b, 能推出注释中的三个式子; 最主要的一点没有证明: 如果gas[0,n-1]>=cost[0,n-1], 那么一定有解; 面试的时候推荐使用最自然的想法, 当然了, 这种方法也得会, 数学真是太关键了

/*
能从a走到b-1, 走不到b, 说明
gas[a]-cost[a] + gas[a+1]-cost[a+1] + ... + gas[b-2]-cost[b-2] >= 0
gas[a]-cost[a] + gas[a+1]-cost[a+1] + ... + gas[b-2]-cost[b-2] + gas[b-1]-cost[b-1] < 0
还说明a可以走到(a,b)之间的任何一点, 设该点为c, 即,
gas[a]-cost[a] + gas[a+1]-cost[a+1] + ... + gas[c-1]-cost[c-1] >= 0
上面3个式子可以简记为
gas[a,b-2] - cost[a,b-2] >= 0
gas[a,b-1] - cost[a,b-1] < 0
gas[a,c-1] - cost[a,c-1] >= 0

结论:如果a不能到达b, 那么从(a,b)之间的任何一个点出发都到达不了b
证明:以(a,b)之间的任意一点c为例, 
gas[c,b-1] - cost[c,b-1] 
= gas[a,b-1]-gas[a,c-1] - (cost[a,b-1] - cost[a,c-1]) 
= gas[a,b-1] - cost[a,b-1] - (gas[a,c-1] - cost[a,c-1])
因为gas[a,b-1] - cost[a,b-1]小于0, 并且(gas[a,c-1] - cost[a,c-1])大于等于0, 所以gas[c,b-1] - cost[c,b-1] 小于0
从而证明了(a,b)之间的任意一点都不能到达b

所以如果a不能到达b, 那么不要从a+1开始重新尝试, 而是从b开始重新尝试

核心:如果gas[0,n-1]>=cost[0,n-1], 那么一定有解
*/
class Solution {
    public int canCompleteCircuit(int[] gas, int[] cost) {
        int n = gas.length;
        int start=0, left=0;
        int global=0;
        for(int i=0; i<n; i++){
            global = global + (gas[i] - cost[i]);
            left = left + (gas[i] - cost[i]);
            //如果left<0, 说明无法从start到达i+1, 需要以i+1为起点重新尝试
            if(left<0){
                start = i+1;
                left = 0;
            }
        }
        return global >= 0 ? start : -1;
    }
}

第一次做; 暴力解法: 从每一个位置开始, 看看能不能走回来, 这是最自然的思路, 但是很慢, 时间复杂度O(N^2);

/*
暴力解法
*/
class Solution {
    public int canCompleteCircuit(int[] gas, int[] cost) {
        int n = gas.length;
        int gasSum=0, costSum=0;
        for(int i=0; i<n; i++){
            gasSum += gas[i];
            costSum += cost[i];
        }
        //汽油总量小于消耗总量, 无解
        if(gasSum < costSum)
            return -1;
        //
        for(int i=0; i<n; i++){
            int left = gas[i];
            int cos = cost[i];
            if(left>=cos){
                int index = i;
                int count = 0;
                while(count<n){
                    index++;
                    index = index % n;
                    left = left - cos + gas[index];
                    cos = cost[index];
                    if(left<cos)
                        break;
                    count++;
                }
                if(count==n)
                    return i;
            }
        }
        return -1;
    }
}

力扣题解; 最优解, 借助数学证明

class Solution {
  public int canCompleteCircuit(int[] gas, int[] cost) {
    int n = gas.length;

    int total_tank = 0;
    int curr_tank = 0;
    int starting_station = 0;
    for (int i = 0; i < n; ++i) {
      total_tank += gas[i] - cost[i];
      curr_tank += gas[i] - cost[i];
      // If one couldn't get here,
      if (curr_tank < 0) {
        // Pick up the next station as the starting one.
        starting_station = i + 1;
        // Start with an empty tank.
        curr_tank = 0;
      }
    }
    return total_tank >= 0 ? starting_station : -1;
  }
}

LeetCode Top Interview Questions 134. Gas Station (Java版; Medium)_第1张图片

你可能感兴趣的:(LeetCode,Top,Interview,Questions,LeetCode)