列表

详情


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
解释:即使打开所有水龙头,你也无法灌溉整个花园。

 

提示:

原站题解

去查看

上次编辑到这里,代码来自缓存 点击恢复默认模板
class Solution { public: int minTaps(int n, vector<int>& ranges) { } };

golang 解法, 执行用时: 8 ms, 内存消耗: 5.3 MB, 提交时间: 2023-02-21 10:58:42

func minTaps(n int, ranges []int) (ans int) {
    rightMost := make([]int, n+1)
    for i, r := range ranges {
        left := max(i-r, 0)
        rightMost[left] = max(rightMost[left], i+r)
    }

    curRight := 0 // 已建造的桥的右端点
    nextRight := 0 // 下一座桥的右端点的最大值
    for i, r := range rightMost[:n] { // 注意这里没有遍历到 n,因为它已经是终点了
        nextRight = max(nextRight, r)
        if i == curRight { // 到达已建造的桥的右端点
            if i == nextRight { // 无论怎么造桥,都无法从 i 到 i+1
                return -1
            }
            curRight = nextRight // 造一座桥
            ans++
        }
    }
    return
}

func max(a, b int) int { if a < b { return b }; return a }

java 解法, 执行用时: 2 ms, 内存消耗: 41.6 MB, 提交时间: 2023-02-21 10:58:28

class Solution {
    public int minTaps(int n, int[] ranges) {
        int[] rightMost = new int[n + 1];
        for (int i = 0; i <= n; ++i) {
            int r = ranges[i];
            // 这样写可以在 i>r 时少写一个 max
            // 凭借这个优化,恭喜你超越了 100% 的用户
            // 说「超越」是因为原来的最快是 2ms,现在优化后是 1ms
            if (i > r) rightMost[i - r] = i + r; // 对于 i-r 来说,i+r 必然是它目前的最大值
            else rightMost[0] = Math.max(rightMost[0], i + r);
        }

        int ans = 0;
        int curRight = 0; // 已建造的桥的右端点
        int nextRight = 0; // 下一座桥的右端点的最大值
        for (int i = 0; i < n; ++i) { // 注意这里没有遍历到 n,因为它已经是终点了
            nextRight = Math.max(nextRight, rightMost[i]);
            if (i == curRight) { // 到达已建造的桥的右端点
                if (i == nextRight) return -1; // 无论怎么造桥,都无法从 i 到 i+1
                curRight = nextRight; // 造一座桥
                ++ans;
            }
        }
        return ans;
    }
}

python3 解法, 执行用时: 76 ms, 内存消耗: 15.5 MB, 提交时间: 2023-02-21 10:58:03

class Solution:
    def minTaps(self, n: int, ranges: List[int]) -> int:
        right_most = [0] * (n + 1)
        for i, r in enumerate(ranges):
            left = max(i - ranges[i], 0)
            right_most[left] = max(right_most[left], i + ranges[i])

        ans = 0
        cur_right = 0  # 已建造的桥的右端点
        next_right = 0  # 下一座桥的右端点的最大值
        for i in range(n):  # 注意这里没有遍历到 n,因为它已经是终点了
            next_right = max(next_right, right_most[i])
            if i == cur_right:  # 到达已建造的桥的右端点
                if i == next_right:  # 无论怎么造桥,都无法从 i 到 i+1
                    return -1
                cur_right = next_right  # 造一座桥
                ans += 1
        return ans

上一题