题目:871. 最低加油次数
方法一:动态规划dp。时间复杂度为0(n^2),细节看注释。
C++版本:
class Solution {
public:
int minRefuelStops(int target, int startFuel, vector<vector<int>>& stations) {
int n=stations.size();
//状态f[i]表示:加油i次可以到达的最远距离
vector<long long> f(n+1,0);
//初始化
f[0]=startFuel;
//第一层for循环枚举每一个加油点
for(int i=0;i<n;i++){
//在到达第i个加油点(从0开始)之前,加油次数最大为i
//枚举所有加油次数j,判断其最远距离是否够达到第i个加油点
for(int j=i;j>=0;j--){
//够达到第i个加油点
if(f[j]>=stations[i][0]){
//更新加j+1次油,可以达到的最远距离
f[j+1]=max(f[j+1],f[j]+stations[i][1]);
}
}
}
//寻找最远距离大于target
for(int i=0;i<=n;i++){
if(f[i]>=target) return i;
}
return -1;
}
};
JAVA版本:
class Solution {
public int minRefuelStops(int target, int startFuel, int[][] stations) {
int n=stations.length;
//状态f[i]表示:加油i次可以到达的最远距离
long[] f = new long[n+1];
//初始化
f[0]=startFuel;
//第一层for循环枚举每一个加油点
for(int i=0;i<n;i++){
//在到达第i个加油点(从0开始)之前,加油次数最大为i
//枚举所有加油次数j,判断其最远距离是否够达到第i个加油点
for(int j=i;j>=0;j--){
//够达到第i个加油点
if(f[j]>=stations[i][0]){
//更新加j+1次油,可以达到的最远距离
f[j+1]=Math.max(f[j+1],f[j]+stations[i][1]);
}
}
}
//寻找最远距离大于target
for(int i=0;i<=n;i++){
if(f[i]>=target) return i;
}
return -1;
}
}
方法二:贪心+优先队列。时间复杂度为0(nlogn) ,细节看注释。
C++版本:
class Solution {
public:
int minRefuelStops(int target, int startFuel, vector<vector<int>>& stations) {
//将tartget也就入到stations里
stations.push_back({target,0});
//优先队列,维护可以加油的油量,从大到小(贪心)
priority_queue<int> qu;
//ans:记录加油的次数,cur:当前可以达到的距离
int ans=0,cur=startFuel;
//枚举所有站点
for(auto x:stations){
//如果当前队列不为空,并且不够到达新的站点x
while(!qu.empty()&&cur<x[0]){
//那就只能加油啦
cur+=qu.top();
qu.pop();
ans++;
}
//还是不能到达
if(cur<x[0]) return -1;
//可以到达,这个油量就可以加入到优先队列当中进行储备
qu.push(x[1]);
}
return ans;
}
};
JAVA版本:
class Solution {
public int minRefuelStops(int target, int startFuel, int[][] stations) {
//ans:记录加油的次数,cur:当前可以达到的距离
int ans=0,cur=startFuel;
//优先队列,维护可以加油的油量,从大到小(贪心)
Queue<Integer> qu= new PriorityQueue<Integer>((a,b) -> b-a);
//枚举所有站点
for(var x:stations){
//如果当前队列不为空,并且不够到达新的站点x
while(!qu.isEmpty()&&cur<x[0]){
//那就只能加油啦
cur+=qu.poll();
ans++;
}
//还是不能到达
if(cur<x[0]) return -1;
//可以到达,这个油量就可以加入到优先队列当中进行储备
qu.add(x[1]);
}
//最后判断能否到达target
while(!qu.isEmpty()&&cur<target){
cur+=qu.poll();
ans++;
}
if(cur<target) return -1;
return ans;
}
}