关于程序员:871-最低加油次数-简单优先队列堆贪心题

41次阅读

共计 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$

贪婪 + 优先队列(堆)

为了不便,咱们记 targett,记 startFuelstart,记 stationsss

咱们能够模仿前进过程,应用 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 多平台公布

正文完
 0