题目描述:
题解:
第一反应是用暴力去模拟,直接模拟需要O(n^2)的时间复杂度。实际上这题有规律可循
规律一:记res_gas为剩余的gas,res_cost为剩余需要消耗的油量,cur为gas[pos]-cost[pos],pos为当前到达加油站的位置。在模拟到一个节点的时候,res_gas < res_cost或者cur<0的时候,无法环驶一圈。
规律二:记以pos_s为起点,在pos的时候发现无法环驶一周,那么pos_s ->pos之间的点都不能作为起点。
简单讨论一下规律二,在pos的时候发现无法环驶一周无非两种情况:
第一种情况cur<0,在pos的时候cur < 0,那么从pos_s+1到pos选择的起点在pos的时候cur都会小于0。由于[pos_s,pos]区间内的每个点cur都是大于等于0的,记gas_sum为出发点到pos gas的总和,cost_sum同理,
此时gas_sum < cost_sum.无论从pos_s+1到pos选择哪个节点作为出发点,每个点的gas都大于等于cost,所以gas_sum始终小于 cost_sum.
第二种情况res_gas < res_cost,论证的方式和第一种情况类似。
规律二比较重要,有了这个规律只需要一次遍历就可以找到合适的起点。
AC代码:
class Solution { public: int canCompleteCircuit(vector<int>& gas, vector<int>& cost) { int Len = gas.size(); int tol_gas,tol_cost; int res,cur; tol_cost = tol_gas = res = cur = 0; int flag = 1; int pos; for(int i=0;i<Len;i++) { tol_gas += gas[i]; tol_cost += cost[i]; } if(tol_gas < tol_cost) return -1; int gas_sum,cost_sum; gas_sum = cost_sum = 0; for(int i=0;i<Len;i++) { if(flag == 1) { pos = i; flag = 0; // continue; } gas_sum += gas[i]; cost_sum += cost[i]; int cur = gas_sum-cost_sum; int res = (tol_gas-gas_sum)-(tol_cost-cost_sum)+cur; if(res < 0 || cur < 0) { // cout << i <<endl; gas_sum = 0; cost_sum = 0; flag = 1; continue; } } if(flag == 1) return -1; return pos; } };