1326. 灌溉花园的最少水龙头数目
题目:
在 x 轴上有一个一维的花园。花园长度为 n,从点 0 开始,到点 n 结束。
花园里总共有 n + 1 个水龙头,分别位于 [0, 1, ..., n] 。
给你一个整数 n 和一个长度为 n + 1 的整数数组 ranges ,其中 ranges[i] (下标从 0 开始)表示:如果打开点 i 处的水龙头,可以灌溉的区域为 [i - ranges[i], i + ranges[i]] 。
请你返回可以灌溉整个花园的 最少水龙头数目 。如果花园始终存在无法灌溉到的地方,请你返回 -1 。
示例 1:
输入:n = 5, ranges = [3,4,1,1,0,0]
输出:1
解释:
点 0 处的水龙头可以灌溉区间 [-3,3]
点 1 处的水龙头可以灌溉区间 [-3,5]
点 2 处的水龙头可以灌溉区间 [1,3]
点 3 处的水龙头可以灌溉区间 [2,4]
点 4 处的水龙头可以灌溉区间 [4,4]
点 5 处的水龙头可以灌溉区间 [5,5]
只需要打开点 1 处的水龙头即可灌溉整个花园 [0,5] 。
示例 2:
输入:n = 3, ranges = [0,0,0,0]
输出:-1
解释:即使打开所有水龙头,你也无法灌溉整个花园。
提示:
1 <= n <= 104
ranges.length == n + 1
0 <= ranges[i] <= 100
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/minimum-number-of-taps-to-open-to-water-a-garden
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:
这道题主要采用贪心算法。
对于第i个位置花盆的灌溉,我们要把所有能灌溉到这盆花的水龙头,找出来,选择哪个能灌溉到“尽量远” (在x轴的右侧,能灌溉得更远)位置的水龙头。
1.首现计算,每个水龙头的灌溉区域range[i] = {left[i], right[i]}。
2.按照起点(left[i])对range数组排序。
3.从花盆角度去遍历,curPos = 0(首现考虑第0盆花的灌溉),对range数组遍历,寻找所以left[i] <= curPos的range[i],因为range数组已经排序,所以这些满足要求的range[i]是顺序排列的,只需遍历即可,但找到某一个range[i],其left[i] > curPos,则说明对于当前curPos的水龙头已经找全,找到这些水龙头中能灌溉得最远的哪一个(right[i]最大)进行选择,即完成了一个水龙头的确定,将curPos设置为max(right[i])(能灌溉最远的水龙头的右侧边界),持续这个过程,直到curPos = n
或者对于当前的CurPos,不存在任何的range[i]满足left[i] <= curPos,此时无解。
代码:
class Solution {
public:
int minTaps(int n, vector<int>& ranges) {
vector<pair<int,int>> data;
data.reserve(ranges.size());
for(int i = 0;i < ranges.size();i++)
data.push_back(make_pair(i - ranges[i],i + ranges[i]));
//按照每一个水龙头可以灌溉的起点,按照从小到大的顺序排列
sort(data.begin(),data.end(),[](const pair<int,int> &a,const pair<int,int> &b)
{
return a.first < b.first;
}
);
int ret = 1;
int curpos = 0;
int tmp = 0;
bool findnext = false;
for(int i = 0;i < data.size();)
{
if(data[i].first <= curpos)
{
tmp = max(tmp,data[i].second);
i++;
findnext = true;
}
else
{
if(!findnext)
return -1;
findnext = false;
if(tmp >= n)
break;
curpos = tmp;
ret++;
}
}
if(tmp < n)
return -1;
else
return ret;
}
};