给定一个由N 个整数组成的数组 arr[] ,其中第i个元素表示喷头的范围,即[i-arr[i], i+arr[i]]它可以浇水,任务是找到最小数量打开洒水器,为画廊的每一株植物浇水。如果不可能给所有植物浇水,则打印-1。
注意:如果arr[i] = -1 ,则洒水器无法打开。
例子:
Input: arr[ ] = {-1, 2, 2, -1, 0, 0}
Output: 2
Explanation:
One of the possible way is:
- Turn on the sprinkler at index 2, it can water the plants in the range [0, 4].
- Turn on the sprinkler at index 2, it can water the plants in the range [5, 5].
Therefore, turning two sprinklers on can water all the plants. Also, it is the minimum possible count of sprinklers to be turned on.
Input: arr[ ] = {2, 3, 4, -1, 2, 0, 0, -1, 0}
Output: -1
方法:上述问题可以使用贪心技术解决。这个想法是首先按左边界对范围进行排序,然后从左开始遍历范围,并在每次迭代中选择喷头可以覆盖的最右边边界,该边界在当前范围内。请按照以下步骤解决问题:
- 初始化一个 vector
> 说V将每个喷头的范围存储为一对。 - 遍历数组arr[] ,如果arr[i]不等于-1,则将 (i-arr[i], i+arr[i])对推入向量V 中。
- 按第一个元素按升序对成对的向量进行排序。
- 初始化2 个变量,例如res和maxRight以存储要打开的最小洒水器并存储数组的最右侧边界。
- 将变量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个然后递增RES和i加1。
- 最后,完成上述步骤后,打印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