汽车加油问题(贪心算法),嵌套循环,复杂度为O(n)

时间:2020-05-07 07:10:17

标签: algorithm while-loop greedy

输入

(1)满油箱汽车可以行驶的最大距离:L km;

(2)一个整数数组[0,x1,x2,…,xn,xn + 1],每个整数表示位置与源点A之间的距离。第一个整数是0,即距离第二距离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

我的疑问是:

  1. 为什么上面代码的时间复杂度是O(n)?至少由于嵌套的while循环,它应该不是O(n ^ 2)吗?
  2. 如何证明“以最远的可燃气体加气”是安全的举动?
  3. 除了使用for循环之外,是否还有其他替代方法可以编写相同的代码?

(简而言之,我理解了逻辑,但我无法对其进行计算)

非常感谢任何资源/帮助/提示/指导!

2 个答案:

答案 0 :(得分:2)

疑问1:

根据执行的操作数计算时间复杂度。不管有多少嵌套循环...

您的第一个while循环将执行到currentPosition <= n,而嵌套的while循环将执行到currentPosition <= n && x[currentPosition + 1] – x[lastPosition] <= L。在此循环中,您将增加currentPostion。因此,您的总操作不可能超过n次。

示例:

array[0, 10, 20, 30]L = 50 ..

在这种情况下,第一个步骤的第一个while循环为true。您为第4个步骤嵌套了true循环。然后在第二步,您的第一个while循环为false ...因此执行了N步...

这就是为什么您的代码很复杂:O ( N ) ...

疑问2:

要最大程度地减少加油量,您需要使用当前的燃油走得更远。如果您使用当前的燃油穿越k站,则无需在1 to k-1站加油。您需要检查的油站,是否有可能用当前的燃油去下一油站。如果您可以使用当前的燃料从当前站点转到下一个站点,则当前站点的加油箱是多余的。

疑问3:

有很多方法可以解决问题...这是另一种方法:

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

答案 1 :(得分:0)

#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 ???