汽车从起点出发驶向目的地,该目的地位于出发位置东面 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
思路1:动态规划
class Solution { public int minRefuelStops(int target, int startFuel, int[][] stations) { int Length = stations.length; long[] dp = new long[Length + 1]; dp[0]=startFuel; // // System.out.println("dp.length"+dp.length); // for(int i=0;i<Length;i++)//第1 次 到第Length 次加油 对应的油为 station【0】【1】 到 station【Length-1】【0】 {//其实这里的i遍历的是车站 for(int t=i;t>=0;t--) {//然后这边必须是逆向更新 因为假设有两个车站,我们需要先更新dp【2】也就是加两次油最远的距离 如果我们先更新了dp【1】的话, // 如果第二个车站的油量>第一个车站 那就会出现第二个车站 加了两次油的情况 比如初始80 【20,40】 【30,80】 【90,100】 //在 i=1的时候,我们先得跟新dp【2】就是加油两次的情况, 如果我们先更新了dp【1】,那这时候dp【1】=80+80>30 那dp2 就又会加一次80 if(dp[t]>=stations[i][0]) { //如果我能到这个车站,那我就加个油 然后加油次数+1 dp[t+1]=Math.max(dp[t+1],dp[t]+stations[i][1]); } } } for (int i = 0; i <= Length; ++i) { if (dp[i] >= target) { return i; } } return -1; } }
2.用大顶堆的贪心来做
class Solution { public int minRefuelStops(int target, int startFuel, int[][] stations) { if(startFuel>=target){ return 0; } //大顶堆 PriorityQueue<Integer> maxheap = new PriorityQueue<Integer>( new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return o2.compareTo(o1); } }); int count = 0; for(int i = 0;i<stations.length;i++){ while(startFuel<stations[i][0]){//无法到达当前加油站时,从优先队列中取油 if(maxheap.size()==0){//队列为空仍然无法到达,说明该加油站不可达。 return -1; }else{ startFuel+=maxheap.poll(); count++; } } maxheap.offer(stations[i][1]); } //注意遍历完加油站还要判断能不能到target while(startFuel<target){ if(maxheap.size()==0){ return -1; }else{ startFuel+=maxheap.poll(); count++; } } return count; } }