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, otherwise return -1.
Note:
The solution is guaranteed to be unique.
题目解析:
方案一:
两个数组之间的值是对应的,那么就将gas[i]-cost[i]经过i结点增加或消耗的油量。这样就直接考虑结点的值,而不用考虑路程中的值,进一步转化成一个一维数组,求从哪一点开始求和,能无负数出现。
常规思维是,让任一点为起始点,开始计算,这样时间复杂度为O(N^2)。但是负数的起始点是不可能的,因此跳过负数为起始的。更进一步,我们选那些s[i-1]为负数,s[i]为大于等于0时,i为起始点,即使i后有连续几个为正数,由于题目中结果唯一,则必须i开始为起始点。这样就更进一步简化。不过实现的时候,有点复杂,我只是选择非负数为起始点,进行递归求解。
如果Judge为false时,才判断深层次的递归返回值。
class Solution { public: int canCompleteCircuit(vector<int> &gas, vector<int> &cost) { if(gas.size() != cost.size()) return -1; res = -1; vector<int> remainder; for(int i = 0;i < gas.size();i++) remainder.push_back(gas[i]-cost[i]); FindIndex(remainder,0); return res; } bool FindIndex(vector<int> &remainder,int index){ if(index >= remainder.size()){ return false; } int i;//写在外面 for(i = index;i < remainder.size();i++){ if(remainder[i] >= 0) //要加等号[2] [2] break; } if(i == remainder.size()){ int res = -1; return false; } return Judge(remainder,i) || FindIndex(remainder,i+1); } bool Judge(vector<int> &remainder,int index){ int sum = 0; for(int i = 0;i < remainder.size();i++){ sum += remainder[(index+i)%remainder.size()]; if(sum < 0) return false; } res = index; return true; } private: int res; };
方案二:
线性时间复杂度O(n)
我们让i=0...n-1开始遍历,期间统计求和sum,如果sum为负数,则肯定从i+1之后开始!所以当j从i+1...n-1后sum始终保持非负数, 就无序验证n个数的和是否一定为正数。这也跟题目有关,保证了有唯一解。
class Solution { public: int canCompleteCircuit(vector<int> &gas, vector<int> &cost) { // Note: The Solution object is instantiated only once and is reused by each test case. int sum=0; int total=0; int start=0; for(int i=0;i<gas.size();i++) { sum+=gas[i]-cost[i]; total+=gas[i]-cost[i]; if(sum < 0) { start=(i+1)%gas.size(); sum=0; } } if(total <0) return -1; else return start; } };
方案三:
以某一结点为起始点i=begin,然后i++,如果sum为负数了,就begin--,并sum+s[begin];当sum再为负数了,就begin--.....这样求解的话,也为线性时间复杂度。
解题思路:
1:假设出发车站为0,初始化车内油量0
2:车内油量=车站油量-消耗
3:如果车内油量大于0,车开到下一车站,否则出发车站前移一个车站
重复2,3步,直到所有车站遍历完。如果车内油量剩余大于等于0,返回出发车站,否则返回-1.
public int canCompleteCircuit(int[] gas, int[] cost) { if (gas == null) { return -1; } // Note: The Solution object is instantiated only once and is reused by each test case. int count = gas.length; int n = 0; int gasInCar = 0; int begin = 0; int end = 0; int i = 0; while (n < count - 1) { gasInCar += gas[i] - cost[i]; if (gasInCar >=0) {//forward end++; i=end; } else { begin--; if (begin < 0) { begin = count - 1; } i = begin; } n++; } gasInCar += gas[i] - cost[i]; if (gasInCar >= 0) { return begin; } else { return -1; } }