Week12 Gas Station
Week12
Greedy
question source: Gas Station
question description
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
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.
解決方法
這道題的標籤是Greedy。是說有一定數量的站,每到一個站能獲得一定數量的汽油,去下一站會消耗不同數量的汽油,問能否從某一個點出發,按順序訪問完所有站一圈,如果能,則返回開頭的點,如果不能,則返回-1。
老規矩,直接暴力解法。從第1個點開始模擬這個 過程,如果不能進行下去,則從下一個點開始,題幹說了,這個解是唯一的,如果找到有一個點開始,能訪問所有的點,則直接返回這個點。
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int size = cost.size();
for(int i = 0; i < size; i++){
int volumn = gas[i];
int j = 0;
while(j != size){
volumn -= cost[(i + j) % size];
if(volumn < 0)
break;
j++;
volumn += gas[(i + j) % size];
}
if(volumn >= 0) return i;
}
return -1;
}
};
這裡沒有涉及任何關於貪心的思想,只是單純地模擬它的過程,過了。演算法時間複雜度是
現在再思考如何利用貪心演算法,在哪一步使用貪心。一個簡單的思想就是,我們爭取去一個站,都是淨獲得汽油的,就是得到的汽油比消耗的汽油要多。積累起來的汽油越多越好。於是演算法就來了,先計算去每一站可以積累多少汽油,然後從第0個開始遍歷,計算開始節點,開始為0,每到一個點計算累積的量,開媽的累積量為0,如果累積量小於0,則說明開始的點不可能為前面的所有節點,只能是後面的節點,因此更新開始的點為後面的第1個節點,同時重置累積量為0。
這裡運用了一個事實,如果總的積累量不為0,那麼此題必定存在解,也就是肯定能找到一個方案使得汽車能依次遍歷所有站點一遍。
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int size = cost.size();
int gain[size];
int sum = 0;
for(int i = 0; i < size; i++){
gain[i] = gas[i] - cost[i];
sum += gain[i];
}
if(sum < 0) return -1;
int begin = 0;
int max = 0;
for(int i = 0; i < size; i++){
max += gain[i];
if(max < 0){
max = 0;
begin = i + 1;
}
}
return begin;
}
};
演算法複雜度是