汽车加油问题(贪心算法),O(n) 复杂度的嵌套 while 循环
Posted
技术标签:
【中文标题】汽车加油问题(贪心算法),O(n) 复杂度的嵌套 while 循环【英文标题】:Car Fueling Problem (Greedy Algorithm), Nested while loop with O(n) complexity 【发布时间】:2020-08-22 09:31:55 【问题描述】:输入
(1)汽车满油可行驶的最大距离:L公里;
(2)一个整数数组,[0, x1, x2, ..., xn, xn+1],每个整数代表一个位置到源点A的距离。第一个整数为0,即距离A和A之间。第二个距离x1,表示第一个加油站和A之间的距离。A和B(目的地)之间有n个加油站。 xn是最后一个加油站到A的距离,xn+1是B到A的距离。
(3)n,即加油站数量。
输出
从 A 到 B 的最小补充次数
代码
numRefills = 0
currentPosition = 0
while(currentPosition <= n)
lastPosition = currentPosition
while(currentPosition <= n && x[currentPosition + 1] – x[lastPosition] <= L)
currentPosition++;
if (currentPosition == lastPosition) return IMPOSSIBLE;
if (currentPosition <= n) numRefills ++;
return numRefills
我的疑问是:
为什么上面代码的时间复杂度是O(n)?由于嵌套的 while 循环,它不应该是 O(n^2) 吗? 如何证明“在最远的地方加油”是安全的举动? 除了使用 for 循环编写相同的代码之外,还有其他替代方法吗?
(总之,我理解了逻辑,但我无法计算它)
非常感谢任何资源/帮助/提示/指导!
【问题讨论】:
【参考方案1】:Coursera 在 C++ 中接受此解决方案
#include <iostream>
#include <vector>
using namespace std;
int compute_min_refills(int dist, int tank, vector<int> &stops)
stops.push_back(dist);
int lastStop = 0;
int numberStop = 0;
int x = 0;
for (int i = 0; i < stops.size() - 1; i++)
if (stops[i] - lastStop <= tank)
x = stops[i];
if (stops[i + 1] - lastStop > tank)
numberStop++;
lastStop = x;
if (tank < stops[i] - lastStop)
//cout << "uzak" << endl;
return -1;
//cout << "x :: " << x << " last stop :: " << lastStop << " number stop :: " << numberStop << endl;
if (dist > lastStop + tank)
return -1;
return numberStop;
int main()
int d = 0;
cin >> d;
int m = 0;
cin >> m;
int n = 0;
cin >> n;
vector<int> stops(n);
for (size_t i = 0; i < n; ++i)
cin >> stops.at(i);
cout << compute_min_refills(d, m, stops) << "\n";
return 0;
【讨论】:
代码在附有解释时会更有帮助。 Stack Overflow 是关于学习的,而不是提供 sn-ps 来盲目复制和粘贴。请edit您的问题并解释它如何回答所提出的具体问题。见How to Answer。【参考方案2】:疑问一:
时间复杂度是根据执行的操作数计算的。不管里面有多少嵌套循环......
你的第一个while循环一直执行到currentPosition <= n
,嵌套的while循环一直执行到currentPosition <= n && x[currentPosition + 1] – x[lastPosition] <= L
..在这个循环中你增加了currentPostion
。所以你的总操作不可能超过n
次。
例子:
array[0, 10, 20, 30]
和 L = 50
..
对于这种情况,您的第一个 while 循环为真,第一步为真。您嵌套循环真为 4 步。然后在第 2 步你的第一个 while 循环错误......所以执行了 N 步......
这就是你的代码复杂的原因:O ( N )
...
疑点二:
为了尽量减少加油,您需要使用当前燃料尽可能多地行驶。如果您使用当前燃料越过k
站,则无需在1 to k-1
站加油。在每个站您都需要检查,是否可以使用当前燃料前往下一站。如果你可以用当前的燃料从当前站到下一个站,那么在当前站加油是多余的。
疑点三:
解决问题的方法有很多种...这里有另一种方法:
numRefills = 0
currentPosition = 0
currentFuel = L
while(currentPosition <= n)
if (currentFuel <= x[currentPosition+1] - x[currentPosition])
currentFuel = L;
numRefills++;
currentFuel -= (x[currentPosition+1] - x[currentPostion]);
if ( currentFuel < 0 )
return Impossible;
currentPosition++;
return numRefills
【讨论】:
感谢@GolamMazid,在复杂的情况下,外部while循环或内部while都可以工作,而不是两者都可以。因为如果 n 被任何循环更新,相同的 n 值将不会重复。如果我在这方面错了,请纠正我。 在您的代码中,如果内部循环执行 x 次,外部循环执行 y 次,则 x+ y 【参考方案3】:#include<bits/stdc++.h>
using namespace std;
int main()
int n,k;
cin>>n>>k;
int arr[k];
for(int i=0;i<k;i++)
cin>>arr[i];
int diff=arr[0],refills=0,fuelCnt=3,flag=1;
for(int i=0;i<k;i++)
if(i!=0)
diff=arr[i]-arr[i-1];
if(fuelCnt < diff)
fuelCnt=3;
refills++;
fuelCnt-=diff;
cout<<"fuelCnt is "<<fuelCnt<<"\n";
if(fuelCnt <0)
flag=0;
break;
//Check if there is enough fuel to reach last stop
diff=n-arr[k-1];
fuelCnt-=diff;
if(fuelCnt <0)
flag=0;
if(fuelCnt < diff)
refills++;
if(flag!=1)
cout<<"Imposible"<<"\n";
else
cout<<refills<<"\n";
check whether code is correct ???
【讨论】:
没有解释的代码转储(使用非标准功能)不是一个好的答案。你能把edit这个变成一个将来可能对某人有帮助的形式吗?。以上是关于汽车加油问题(贪心算法),O(n) 复杂度的嵌套 while 循环的主要内容,如果未能解决你的问题,请参考以下文章