📜  为植物浇水所需的最少喷水器

📅  最后修改于: 2021-09-04 13:03:36             🧑  作者: Mango

给定一个由N 个整数组成的数组 arr[] ,其中第i元素表示喷头的范围,即[i-arr[i], i+arr[i]]它可以浇水,任务是找到最小数量打开洒水器,为画廊的每一株植物浇水。如果不可能给所有植物浇水,则打印-1。
注意:如果arr[i] = -1 ,则洒水器无法打开。

例子:

方法:上述问题可以使用贪心技术解决。这个想法是首先按左边界对范围进行排序,然后从左开始遍历范围,并在每次迭代中选择喷头可以覆盖的最右边边界,该边界在当前范围内。请按照以下步骤解决问题:

  • 初始化一个 vector> 说V将每个喷头的范围存储为一对。
  • 遍历数组arr[] ,如果arr[i]不等于-1,则将 (i-arr[i], i+arr[i])对推入向量V 中
  • 按第一个元素按升序对成对的向量进行排序。
  • 初始化2 个变量,例如resmaxRight以存储要打开的最小洒水器并存储数组的最右侧边界。
  • 将变量i初始化为0以迭代V。
  • 迭代直到maxRight小于N并执行以下步骤:
    • 如果i等于V.size()V[i] .first大于 maxRight 则打印-1并返回。
    • 将当前喷头的右边界存储在变量 say currMax 中
    • 现在迭代直到i+1小于V.size()并且V[i+1] .first小于或等于 maxRight 然后在每次迭代中将 i增加1并将currMax更新为currMax = min(currMax, V[ i].second)。
    • 如果currMax小于maxRight则打印-1并返回。
    • 更新maxRight作为maxRight = currMax + 1个然后递增RESi1。
  • 最后,完成上述步骤后,打印res作为答案。

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
  
// Function to find minimum number of
// sprinkler to be turned on
int minSprinklers(int arr[], int N)
{
    // Stores the leftmost and rightmost
    // point of every sprinklers
    vector > V;
    // Traverse the array arr[]
    for (int i = 0; i < N; i++) {
        if (arr[i] > -1) {
            V.push_back(
                pair(i - arr[i], i + arr[i]));
        }
    }
    // Sort the array sprinklers in
    // ascending order by first element
    sort(V.begin(), V.end());
  
    // Stores the rightmost range
    // of a sprinkler
    int maxRight = 0;
    // Stores minimum sprinklers
    // to be turned on
    int res = 0;
  
    int i = 0;
  
    // Iterate until maxRight is
    // less than N
    while (maxRight < N) {
  
        // If i is equal to V.size()
        // or V[i].first is greater
        // than maxRight
  
        if (i == V.size() || V[i].first > maxRight) {
            return -1;
        }
        // Stores the rightmost boundary
        // of current sprinkler
        int currMax = V[i].second;
  
        // Iterate until i+1 is less
        // than V.size() and V[i+1].first
        // is less than or equal to maxRight
        while (i + 1 < V.size()
               && V[i + 1].first <= maxRight) {
  
            // Increment i by 1
            i++;
            // Update currMax
            currMax = max(currMax, V[i].second);
        }
  
        // If currMax is less than the maxRight
        if (currMax < maxRight) {
            // Return -1
            return -1;
        }
        // Increment res by 1
        res++;
  
        // Update maxRight
        maxRight = currMax + 1;
  
        // Increment i by 1
        i++;
    }
    // Return res as answer
    return res;
}
  
// Drive code.
int main()
{
    // Input
    int arr[] = { -1, 2, 2, -1, 0, 0 };
    int N = sizeof(arr) / sizeof(arr[0]);
  
    // Function call
    cout << minSprinklers(arr, N);
}


输出:
2

时间复杂度: O(N * log(N))
辅助空间: O(N)

如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live