Java 求解加油站
Posted 南淮北安
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 求解加油站相关的知识,希望对你有一定的参考价值。
一、题目
在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升。
你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。
如果你可以绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1。
说明:
- 如果题目有解,该答案即为唯一答案。
- 输入数组均为非空数组,且长度相同。
- 输入数组中的元素均为非负数。
二、题解
暴力解法: 遍历每一个加油站,模拟一圈,如果跑了一圈,没有断油,而且最后油量大于等于0,说明这个起点是可以的。
for 循环适合模拟从头到尾的遍历,而 while 循环适合模拟环形遍历,要善于使用 while
贪心解法:
如果总油量减去总消耗大于等于零那么说明,一定可以跑完一圈,说明各个站点的加油站,剩余油量想加一定是可以大于等于零的
i从0开始累加rest[i],和记为curSum,一旦curSum小于零,说明[0, i]区间都不能作为起始位置,起始位置从i+1算起,再从0计算curSum。
那么为什么一旦[i,j] 区间和为负数,起始位置就可以是j+1呢,j+1后面就不会出现更大的负数?
那么为什么一旦[i,j] 区间和为负数,起始位置就可以是j+1呢,j+1后面就不会出现更大的负数?
如果出现更大的负数,就是更新j,那么起始位置又变成新的j+1了。
而且j之前出现了多少负数,j后面就会出现多少正数,因为耗油总和是大于零的(前提我们已经确定了一定可以跑完全程)。
三、代码
暴力解法:
class Solution
public int canCompleteCircuit(int[] gas, int[] cost)
int res;
int index;
for (int i = 0; i < gas.length; i++)
res = gas[i] - cost[i];
// 环形绕,所以写成这种写法
index = (i + 1) % gas.length;
// 如果能循环一周,保持不空油,则 i 点可以当做起点
while (res >= 0 && index !=i)
res += gas[index] - cost[index];
index = (index + 1) % gas.length;
if (res >= 0)
return i;
return -1;
贪心解法:
class Solution
public int canCompleteCircuit(int[] gas, int[] cost)
// 记录当前总和
int curSum = 0;
// 记录总和
int totalSum = 0;
int start = 0;
for (int i = 0; i < gas.length; i++)
curSum += gas[i] - cost[i];
totalSum += gas[i] - cost[i];
// 如果当前总和小于0,说明当前值及其前的点,都不适合作为起点
if (curSum < 0)
start = i + 1;
curSum = 0;
// 如果总的差值之和小于0,说明无法环绕一周
if (totalSum < 0)
return -1;
return start;
四、总结
暴力解法注意,while 的应用,for 循环适合遍历,while 适合环形遍历,以及环形的处理:
index = (index + 1) % gas.length;
贪心解法,局部最优,推出全局最优
以上是关于Java 求解加油站的主要内容,如果未能解决你的问题,请参考以下文章