共计 1978 个字符,预计需要花费 5 分钟才能阅读完成。
题目形容
这是 LeetCode 上的 871. 最低加油次数 ,难度为 艰难。
Tag :「贪婪」、「优先队列(堆)」、「模仿」
汽车从终点登程驶向目的地,该目的地位于登程地位东面 target
英里处。
沿途有加油站,每个 station[i]
代表一个加油站,它位于登程地位东面 station[i][0]
英里处,并且有 station[i][1]
升汽油。
假如汽车油箱的容量是有限的,其中最后有 startFuel
升燃料。它每行驶 $1$ 英里就会用掉 $1$ 升汽油。
当汽车达到加油站时,它可能停下来加油,将所有汽油从加油站转移到汽车中。
为了达到目的地,汽车所必要的最低加油次数是多少?如果无奈达到目的地,则返回 $-1$。
留神:如果汽车达到加油站时残余燃料为 $0$,它依然能够在那里加油。如果汽车达到目的地时残余燃料为 $0$,依然认为它曾经达到目的地。
示例 1:
输出:target = 1, startFuel = 1, stations = []
输入:0
解释:咱们能够在不加油的状况下达到目的地。
示例 2:
输出:target = 100, startFuel = 1, stations = [[10,100]]
输入:-1
解释:咱们无奈到达目的地,甚至无奈达到第一个加油站。
示例 3:
输出: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$
贪婪 + 优先队列(堆)
为了不便,咱们记 target
为 t
,记 startFuel
为 start
,记 stations
为 ss
。
咱们能够模仿前进过程,应用 n
代表加油站总个数,idx
代表通过的加油站下标,应用 remain
代表以后有多少油(起始有 remain = start
),loc
代表走了多远,ans
代表答案(至多须要的加油次数)。
只有 loc < t
,代表还没达到(通过)指标地位,咱们能够持续模仿前进过程,每次将 remain
累加到 loc
中,含意为应用完残余的油量,能够去到的最远距离,同时将所在位置 ss[idx][0] <= loc
的加油站数量退出优先队列(大根堆,依据油量排倒序)中,再次查看是否满足 loc < t
(下次循环),此时因为清空了残余油量 remain
,咱们尝试从优先队列(大根堆)中取出过往油量最大的加油站并进行加油(同时对加油次数 ans
进行加一操作),应用新的残余油量 remain
反复上述过程,直到满足 loc >= t
或无油可加。
容易证实该做法的正确性:同样是耗费一次加油次数,始终抉择油量最大的加油站进行加油,能够确保不存在更优的后果。
代码:
class Solution {public int minRefuelStops(int t, int start, int[][] ss) {PriorityQueue<Integer> q = new PriorityQueue<>((a,b)->b-a);
int n = ss.length, idx = 0;
int remain = start, loc = 0, ans = 0;
while (loc < t) {if (remain == 0) {if (!q.isEmpty() && ++ans >= 0) remain += q.poll();
else return -1;
}
loc += remain; remain = 0;
while (idx < n && ss[idx][0] <= loc) q.add(ss[idx++][1]);
}
return ans;
}
}
- 工夫复杂度:$O(n\log{n})$
- 空间复杂度:$O(n)$
最初
这是咱们「刷穿 LeetCode」系列文章的第 No.871
篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,局部是有锁题,咱们将先把所有不带锁的题目刷完。
在这个系列文章外面,除了解说解题思路以外,还会尽可能给出最为简洁的代码。如果波及通解还会相应的代码模板。
为了不便各位同学可能电脑上进行调试和提交代码,我建设了相干的仓库:https://github.com/SharingSou…。
在仓库地址里,你能够看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其余优选题解。
本文由 mdnice 多平台公布