返回介绍

solution / 0800-0899 / 0871.Minimum Number of Refueling Stops / README

发布于 2024-06-17 01:03:33 字数 4800 浏览 0 评论 0 收藏 0

871. 最低加油次数

English Version

题目描述

汽车从起点出发驶向目的地,该目的地位于出发位置东面 target 英里处。

沿途有加油站,用数组 stations 表示。其中 stations[i] = [positioni, fueli] 表示第 i 个加油站位于出发位置东面 positioni 英里处,并且有 fueli 升汽油。

假设汽车油箱的容量是无限的,其中最初有 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 升。然后开车抵达目的地。
沿途在两个加油站停靠,所以返回 2 。

 

提示:

  • 1 <= target, startFuel <= 109
  • 0 <= stations.length <= 500
  • 1 <= positioni < positioni+1 < target
  • 1 <= fueli < 109

解法

方法一:贪心 + 优先队列(大根堆)

利用优先队列记录所有已经到达过的加油站的加油量,每次当油量不足时,从队列中取出最大加油量,并累计加油次数 ans。

时间复杂度 $O(nlogn)$。其中 $n$ 表示数组 stations 的长度。

class Solution:
  def minRefuelStops(
    self, target: int, startFuel: int, stations: List[List[int]]
  ) -> int:
    q = []
    prev = ans = 0
    stations.append([target, 0])
    for a, b in stations:
      d = a - prev
      startFuel -= d
      while startFuel < 0 and q:
        startFuel -= heappop(q)
        ans += 1
      if startFuel < 0:
        return -1
      heappush(q, -b)
      prev = a
    return ans
class Solution {
  public int minRefuelStops(int target, int startFuel, int[][] stations) {
    PriorityQueue<Integer> q = new PriorityQueue<>((a, b) -> b - a);
    int n = stations.length;
    int prev = 0, ans = 0;
    for (int i = 0; i < n + 1; ++i) {
      int d = (i < n ? stations[i][0] : target) - prev;
      startFuel -= d;
      while (startFuel < 0 && !q.isEmpty()) {
        startFuel += q.poll();
        ++ans;
      }
      if (startFuel < 0) {
        return -1;
      }
      if (i < n) {
        q.offer(stations[i][1]);
        prev = stations[i][0];
      }
    }
    return ans;
  }
}
class Solution {
public:
  int minRefuelStops(int target, int startFuel, vector<vector<int>>& stations) {
    priority_queue<int> q;
    stations.push_back({target, 0});
    int ans = 0, prev = 0;
    for (auto& s : stations) {
      int d = s[0] - prev;
      startFuel -= d;
      while (startFuel < 0 && !q.empty()) {
        startFuel += q.top();
        q.pop();
        ++ans;
      }
      if (startFuel < 0) return -1;
      q.push(s[1]);
      prev = s[0];
    }
    return ans;
  }
};
func minRefuelStops(target int, startFuel int, stations [][]int) int {
  stations = append(stations, []int{target, 0})
  ans, prev := 0, 0
  q := &hp{}
  heap.Init(q)
  for _, s := range stations {
    d := s[0] - prev
    startFuel -= d
    for startFuel < 0 && q.Len() > 0 {
      startFuel += q.pop()
      ans++
    }
    if startFuel < 0 {
      return -1
    }
    q.push(s[1])
    prev = s[0]
  }
  return ans
}

type hp struct{ sort.IntSlice }

func (h hp) Less(i, j int) bool { return h.IntSlice[i] > h.IntSlice[j] }
func (h *hp) Push(v any)    { h.IntSlice = append(h.IntSlice, v.(int)) }
func (h *hp) Pop() any {
  a := h.IntSlice
  v := a[len(a)-1]
  h.IntSlice = a[:len(a)-1]
  return v
}
func (h *hp) push(v int) { heap.Push(h, v) }
func (h *hp) pop() int   { return heap.Pop(h).(int) }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文