LeetCode871. 最低加油次数
题目描述
本题目来自LeetCode上的『871. 最低加油次数』
汽车从起点出发驶向目的地,该目的地位于出发位置东面 target
英里处。
沿途有加油站,每个 station[i]
代表一个加油站,它位于出发位置东面 station[i][0]
英里处,并且有 station[i][1]
升汽油。
假设汽车油箱的容量是无限的,其中最初有 startFuel
升燃料。它每行驶 1 英里就会用掉 1 升汽油。
当汽车到达加油站时,它可能停下来加油,将所有汽油从加油站转移到汽车中。
为了到达目的地,汽车所必要的最低加油次数是多少?如果无法到达目的地,则返回 -1
。
注意:如果汽车到达加油站时剩余燃料为 0,它仍然可以在那里加油。如果汽车到达目的地时剩余燃料为 0,仍然认为它已经到达目的地。
示例1:
输入:target = 100, startFuel = 10, stations = [[10,60],[20,30],[30,30],[60,40]]
输出:2
解释:
我们出发时有 10 升燃料。
我们开车来到距起点 10 英里处的加油站,消耗 10 升燃料。将汽油从 0 升加到 60 升。
然后,我们从 10 英里处的加油站开到 60 英里处的加油站(消耗 50 升燃料),
并将汽油从 10 升加到 50 升。然后我们开车抵达目的地。
我们沿途在1两个加油站停靠,所以返回 2 。
提示
1 <= target, startFuel, stations[i][1] <= 10^9
0 <= stations.length <= 500
0 < stations[0][0] < stations[1][0] < ... < stations[stations.length-1][0] < target
题解1 - 贪心
根据贪心的思想,如果当前油量 curr
能够到达加油站,那么就不需要加油,并将路过的加油站的油量加入大根堆中。
如果当前油量不足以到达下一个加油站,那么选择已经路过的加油站中油量最多的一个进行加油。
如果加完路过的所有的加油站的油,还是无法到达下一个加油站,那么返回 -1
。
代码
class Solution {
public:
int minRefuelStops(int target, int startFuel, vector<vector<int>>& stations) {
priority_queue<int> pq;
int curr = startFuel, ans = 0;
int i = 0, n = stations.size();
while (curr < target) {
if (i < n && curr >= stations[i][0]) {
pq.push(stations[i++][1]);
} else {
if (!pq.empty()) {
curr += pq.top();
pq.pop();
++ans;
} else {
return -1;
}
}
}
return ans;
}
};
复杂度分析
- 时间复杂度:$O(n\log{n})$
- 空间复杂度:$O(n)$
题解2 - 动态规划
使用 $dp[i]$ 表示第 $i$ 次加油所能达到的最大距离。每到达新的加油站,就更新之前所有 $dp$,如果不能到达下一个加油站,那么返回 -1
。
代码
class Solution {
public:
int minRefuelStops(int target, int startFuel, vector<vector<int>>& stations) {
long dp[510] = {0};
int n = stations.size();
dp[0] = startFuel;
for (int i = 0; i < n; ++i) {
for (int j = i; j >= 0; --j) {
if (dp[j] >= stations[i][0]) {
dp[j + 1] = max(dp[j + 1], dp[j] + stations[i][1]);
}
}
}
for (int i = 0; i <= n; ++i) {
if (dp[i] >= target) {
return i;
}
}
return -1;
}
};
复杂度分析
- 时间复杂度:$O(n^2)$
- 空间复杂度:$O(n)$