题意
即有一个无限油箱的小车在很长的一段环路上行驶,途中有加油站,加油站可以补给一次汽油,小车刚开始没有油,可以任意选择某个加油站作为出生点,问小车在哪个点能够绕环路一圈?若存在,请给出第一个点的位置
输入:
①加油站储存的汽油数
②加油站之间的汽油损耗数
输出:
第一个可行加油站的位置或不存在,即-1
思路
如果用暴力解法,可以在 O ( N 2 ) O(N^2) O(N2)时间复杂度解决,但是可以观察到计算不同出生点的过程中包含一些重复的计算量,因此启发我们可以根据之前点的计算跳过后续某些加油站
证:对于某一个点
x
x
x,其第一次无法到达的点为y,这表明
∑
i
=
x
y
g
a
s
[
i
]
<
∑
i
=
x
y
c
o
s
t
[
i
]
\sum_{i=x}^{y}gas[i]<\sum_{i=x}^{y}cost[i]
i=x∑ygas[i]<i=x∑ycost[i]
∑
i
=
x
j
g
a
s
[
i
]
≥
∑
i
=
x
j
c
o
s
t
[
i
]
\sum_{i=x}^{j}gas[i] \ge \sum_{i=x}^{j}cost[i]
i=x∑jgas[i]≥i=x∑jcost[i]其中
j
j
j表示
[
x
,
y
)
[x,y)
[x,y)中任意一点
那么我们也可以证明
[
x
,
y
)
[x,y)
[x,y)中任意一点
j
j
j也无法到达
y
y
y
∑
i
=
j
y
g
a
s
[
i
]
=
∑
i
=
x
y
g
a
s
[
i
]
−
∑
i
=
x
j
−
1
g
a
s
[
i
]
\sum_{i=j}^{y}gas[i]=\sum_{i=x}^{y}gas[i]-\sum_{i=x}^{j-1}gas[i]
i=j∑ygas[i]=i=x∑ygas[i]−i=x∑j−1gas[i]
<
∑
i
=
x
y
c
o
s
t
[
i
]
−
∑
i
=
x
j
−
1
c
o
s
t
[
i
]
=
∑
i
=
j
y
c
o
s
t
[
i
]
<\sum_{i=x}^{y}cost[i]-\sum_{i=x}^{j-1}cost[i]=\sum_{i=j}^{y}cost[i]
<i=x∑ycost[i]−i=x∑j−1cost[i]=i=j∑ycost[i]
所以我们在判断某点无法环绕一圈时,也判断了之间的点无法环绕一圈,这样每个点只需要计算一遍,时间复杂度降低至
O
(
N
)
O(N)
O(N)
代码
class Solution {
public int canCompleteCircuit(int[] gas, int[] cost) {
for (int i=0;i< gas.length;i++) {
int j = i, count = 0;
while (j<i+ gas.length) {
count += gas[j% gas.length]-cost[j% gas.length];
if (count<0) {
break;
}
j++;
}
if (j==i+ gas.length) {
return i;
} else {
i=j;
}
}
return -1;
}
}