0
点赞
收藏
分享

微信扫一扫

[leetcode每日一题]2.21

​​1326. 灌溉花园的最少水龙头数目​​

难度困难131

在 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:

[leetcode每日一题]2.21_区间覆盖问题

输入: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​

Solution

解法1:经典的区间规划问题,可以将左端点从小到大排序,之后贪心枚举能达到的最右端点。

代码(C++)

class Solution {
public:
int minTaps(int n, vector<int>& ranges) {
vector<vector<int>> intervals;
for(int i = 0;i<=n;i++){
intervals.push_back({i-ranges[i],i+ranges[i]});
}
sort(intervals.begin(), intervals.end(), [&](auto& a, auto& b){return a[0]<b[0];});
intervals.push_back({n+1, 0});
int cur_right = 0;
int tmp = 0;
int res = 0;
for(int i=0;i<=n;i++){
if(intervals[i][0] <= cur_right){
tmp = max(intervals[i][1], tmp);
}
if(intervals[i+1][0] > cur_right){
cur_right = tmp;
res += 1;
}
if(cur_right >= n)break;
}
if(cur_right >= n)return res;
return -1;
}
};

其实不需要排序,直接用一个长度为n+1的数组记录初始和结束位置即可。

[leetcode每日一题]2.21_区间覆盖问题_02

class Solution {
public:
int minTaps(int n, vector<int>& ranges) {
vector<int> rightMost(n + 1);
iota(rightMost.begin(), rightMost.end(), 0);
for (int i = 0; i <= n; i++) {
int start = max(0, i - ranges[i]);
int end = min(n, i + ranges[i]);
rightMost[start] = max(rightMost[start], end);
}
int last = 0, ret = 0, pre = 0;
for (int i = 0; i < n; i++) {
last = max(last, rightMost[i]);
if (i == last) {
return -1;
}
if (i == pre) {
ret++;
pre = last;
}
}
return ret;
}
};

作者:LeetCode-Solution
链接:https://leetcode.cn/problems/minimum-number-of-taps-to-open-to-water-a-garden/solution/guan-gai-hua-yuan-de-zui-shao-shui-long-tou-shu-3/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

当然,也可以用dp来做。创建一个dp[n+1],然后遍历每一个点更新状态即可。

class Solution {
public:
int minTaps(int n, vector<int>& ranges) {
vector<pair<int, int>> intervals;
for (int i = 0; i <= n; i++) {
int start = max(0, i - ranges[i]);
int end = min(n, i + ranges[i]);
intervals.emplace_back(start, end);
}
sort(intervals.begin(), intervals.end());
vector<int> dp(n + 1, INT_MAX);
dp[0] = 0;
for (auto [start, end] : intervals) {
if (dp[start] == INT_MAX) {
return -1;
}
for (int j = start; j <= end; j++) {
dp[j] = min(dp[j], dp[start] + 1);
}
}
return dp[n];
}
};

作者:LeetCode-Solution
链接:https://leetcode.cn/problems/minimum-number-of-taps-to-open-to-water-a-garden/solution/guan-gai-hua-yuan-de-zui-shao-shui-long-tou-shu-3/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


举报

相关推荐

0 条评论