汽车加油问题(贪心算法),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 &lt;= n,嵌套的while循环一直执行到currentPosition &lt;= n &amp;&amp; x[currentPosition + 1] – x[lastPosition] &lt;= 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 循环的主要内容,如果未能解决你的问题,请参考以下文章

汽车加油问题--贪心算法

贪心算法求解汽车加油问题

贪心算法之虚拟汽车加油问题

贪心算法的汽车加油问题(使列表索引超出范围)

贪心算法--汽车加油问题

[贪心算法]加油站