Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情。
一.题目介绍
1.题目来源
链接:LeetCode
2.题目
在一条环路上有n个加油站,其中第i个加油站有汽油 gas[i] 升。
你有一辆油箱容量无限的的汽车,从第i个加油站开往第i+1个加油站需要消耗汽油cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。
给定两个整数数组gas和cost ,如果你可以绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1 。如果存在解,则保证它是唯一的。
二.具体实现
1.实现思路
考虑暴力破解,一方面是验证下自己对题目的理解是否正确,另一方面后续的优化也可以从这里入手。
考虑从第 0 个点出发,能否回到第 0 个点。
考虑从第 1 个点出发,能否回到第 1 个点。
考虑从第 2 个点出发,能否回到第 2 个点。
......
考虑从第 n 个点出发,能否回到第 n 个点。
由于是个圆,得到下一个点的时候我们需要取余数。
另外针对暴力法,优化算法主要从圆上入手
2.实现代码
1)暴力法,缺点很明显,每一步都需要避开圆
public int canCompleteCircuit(int[] gas, int[] cost) {
//汽油
int n = gas.length;
//考虑从每个点出发
for (int i = 0; i < n; i++) {
int j = i;
int remain = gas[i];
//说明可以到达下一个点
while (remain -cost[j] >=0){
//减去花费的 + 新的补给的
remain = remain - cost[j] + gas[(j+1) % n];
j = (j + 1) % n;
//j 回到了 i
if (j == i) {
return i;
}
}
}
return -1;
}
2)针对暴力法的优化算法
public int canCompleteCircuit1(int[] gas, int[] cost) {
int n = gas.length;
for (int i = 0; i < n; i++) {
int j = i;
int remain = gas[i];
while (remain - cost[j] >= 0) {
//减去花费的加上新的点的补给
remain = remain - cost[j] + gas[(j + 1) % n];
j = (j + 1) % n;
//j 回到了 i
if (j == i) {
return i;
}
}
if (j < i) {
return -1;
}
//i 直接跳到 j,外层 for 循环执行 i++,相当于从 j + 1 开始考虑
i = j;
}
return -1;
}
3.运行结果
三.题后思考
可以看出来,即使是优化后的算法,其实也不是最优解。有时候自己一直找不到突破口是因为自己把问题想困难了,其实有的问题很简单,需要不断的分解。无论怎么样,这也是自己思考后的产物,算法题,每做一题再去看题友的解决方案都有所收获,哦,原来这个题还能这么做,也算是每天进步一点点吧,加油!