[LeetCode]134. 加油站(java实现)贪心、双指针
1. 题目
2. 读题(需要重点注意的东西)
思路(贪心、双指针):
由于是走一圈,我们将加油站复制一遍放到原加油站数组后,起点start从第1个加油站遍历到第n个加油站,如果end - start + 1 == n
,则说明能够走一圈。
- 首先用每个位置的 gas 减去 cost 求出当前位置的真正花费 sum,然后将 sum 数组扩展为 2n,使得
sum[i + n] = sum[i]
- 定义两个指针 start 和 end,分别表示当前的起点,和在这个起点下能走到的终点,tot 为当前油量,当在某一个节点
sum < 0
时,说明达到了终点 - 如果
end - start + 1 == n
,返回true - 否则start++
时间复杂度为O(n2)
优化:
假设从当前start开始,end - start + 1 < n
,那么从start到end中的任何一个节点开始,都不可能有end - start + 1 == n
,因此如果end - start + 1 < n
,则直接将start = end + 1
,从而将时间复杂度优化成O(n)。
为什么?
从start可以走到end,那么说明当汽车达到第k个节点的汽油量是大于或者等于0
的(未加gas[k]),此时都不能行驶一圈。
那么如果当k是起始节点的时候,汽油量初始为0(未加gas[k]),就更不可能不能行驶一圈了。
3. 解法
---------------------------------------------------解法---------------------------------------------------:
class Solution {
public int canCompleteCircuit(int[] gas, int[] cost) {
int n = gas.length;
int[] sum = new int[2 * n];
for(int i = 0;i < n * 2;i++)
sum[i] = gas[i % n] - cost[i % n];
int start = 0, end = 0, tot = 0;
while(start < n && end <= 2 * n){
tot += sum[end];
// 如果当前汽油量小于0了
while(tot < 0){
tot = 0; // 更新start、tot
start = end + 1; // 优化
}
if(end - start + 1 == n) return start;
end++;
}
return -1;
}
}
可能存在的问题: