题目:
在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升。
你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。
如果你可以绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1。
说明:
如果题目有解,该答案即为唯一答案。
输入数组均为非空数组,且长度相同。
输入数组中的元素均为非负数。
class Solution {
public:
/*************************法一: 暴力解法**************************************/
// int canCompleteCircuit(vector<int>& gas, vector<int>& cost)
// {
// for(int i = 0; i < gas.size(); i++)
// {
// int rest = gas[i] - cost[i];
// // 这个if 条件可以与 while 合并了 if(rest < 0) continue;
// // 内层循环中 因为要循环转一整圈,这里就不能 j < gas.size 了,因为这样就转不了一圈了。
// // &&&&&&&& 1、注意这里怎么给 j 赋值的,因为是转圈圈,通过取余获得
// int j = (i + 1) % gas.size();
// // &&&&&&& 2、这里为什么是 rest > 0 ,而没有取等呢?,我感觉应该取等号,结果是取等也是对的
// while(rest >= 0 && j != i) // &&&&&& 3、妙~ 仅用 j != i 就实现了转一圈
// {
// rest += (gas[j] - cost[j]);
// j = (j + 1) % gas.size(); // &&&&&& 4、
// }
// // 如果以 i 为起点转一圈,剩余的油量 大于等于 0 ,则返回该起始位置
// if(rest >= 0 && j == i) return i;
// }
// return -1;
// }
/********************法二: 贪心思路一*****************************/
// // 直接从全局最优的角度来考虑问题
// int canCompleteCircuit(vector<int>& gas, vector<int>& cost)
// {
// int curSum = 0;
// int min = INT_MAX;
// // 先遍历一遍,计算出 gas[i] - cost[i] 的总和,以及出现的最小值
// for(int i = 0; i < gas.size(); i++)
// {
// int rest = gas[i] - cost[i];
// curSum += rest;
// if(curSum < min)
// {
// min = curSum;
// }
// }
// // 情况一:如果gas的总和小于cost总和,那么无论从哪里出发,一定是跑不了一圈的
// if(curSum < 0) return -1;
// // 情况二:如果累加过程中没有出现负数,说明从0出发,油就没有断过,那么0就是起点
// if(min >= 0) return 0;
// // 情况三:如果累加的最小值是负数,汽车就要从非0节点出发,从后向前,
// // 看哪个节点能这个负数填平,能把这个负数填平的节点就是出发节点。
// for(int i = gas.size() - 1; i >= 0; i--)
// {
// min += gas[i] - cost[i];
// if(min >= 0) return i;
// }
// return -1;
// }
/********************法二: 贪心思路二*****************************/
int canCompleteCircuit(vector<int>& gas, vector<int>& cost)
{
// 贪心:
// 局部最优:当前累加的和 curSum 一旦小于0,起始位置至少是 i+1
// 全局最优:找到可以泡一圈的起始位置
int curSum = 0;
int sumSum = 0;
int start = 0;
for(int i = 0; i < gas.size(); i++)
{
curSum += gas[i] - cost[i];
sumSum += gas[i] - cost[i];
if(curSum < 0)
{
// 当 curSum < 0,说明起始位置至少要从 i+1 开始。注意是 i+1 哦~~
curSum = 0;
start = i + 1;
}
}
if(sumSum < 0)
{
return -1;
}
return start;
}
};