3种解法 - 灌溉花园的最少水龙头数目

给定一个一维花园和灌溉范围,该文章探讨了如何使用深度优先搜索、广度优先搜索和贪心算法找到灌溉整个花园所需的最少水龙头数目。深度优先搜索虽然思路简单,但时间复杂度过高;广度优先搜索通过优化空间利用率,提高了效率,但仍然可能超时;贪心算法则通过每次选取最大覆盖范围的水龙头,达到较高的效率和空间复杂度。
摘要由CSDN通过智能技术生成


题目

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

输入:n = 7, ranges = [1,2,1,0,2,1,0,1]
输出:3
示例 4:

输入:n = 8, ranges = [4,0,0,0,0,0,0,0,4]
输出:2
示例 5:

输入:n = 8, ranges = [4,0,0,0,4,0,0,0,4]
输出:1

提示:

1 <= n <= 10^4
ranges.length == n + 1
0 <= ranges[i] <= 100


解法一(深度优先搜索)

思路:核心就是找出可以覆盖[0,n]的最小数组个数,那就把数组的头按递归排序,通过头尾交集来检查区域之间是否连续

  1. 求出各个数据覆盖的区域
  2. 找出无效或者其它区域的子域,仅对有效区域进行计算
  3. 为了方便递归,先对所有区域的开端进行递增排序
  4. 对每个区域开始,从前到后依次进行递归查询,如果满足条件,则记录最小的值,是深度优先算法的思想。
  • 时间复杂度:O(n2+n!),n2是主函数的前三步,n!是第四步的递归函数
  • 空间复杂度:O(n),存储区域的数组r

这是个顺序思维,可以满足功能要求成功执行,但时间复杂度太高了,结果就是仅通过了13/31个测试用例,未通过的超时了,超时测试用例及代码如下:

68
[0,0,0,1,4,2,2,2,2,4,0,0,0,5,4,0,0,5,3,0,1,1,5,1,1,2,4,1,0,4,3,5,1,0,3,3,4,2,2,4,3,1,1,0,4,0,2,1,4,0,0,3,3,1,1,4,4,2,0,3,4,0,1,5,3,0,1,0,2]
public class Solution {
   
        public int getLinkCount(int[,] r,List<int> rList,int count,int len)
        {
   
            int minTemp = len;
            bool flag = true;
            for (int i = 1; i < rList.Count; i++)
            {
   //区域不连续
                if (r[rList[i - 1], 1] < r[rList[i], 0])
                {
   
                    flag = false;
                    break;
                }
            }
            if (flag && r[rList[0], 0] <= 0 && r[rList[rList.Count - 1], 1] >= len-1)
                return rList.Count;

            for(int i=count+1;i<len;i++)
            {
   //从前到后做深度优先搜索的递归
                if(r[i,2] == 1)
                {
   
                    rList.Add(i);
                    int tmp = getLinkCount(r, rList, i, len);
                    if (tmp > 0 && tmp < minTemp) 
                        minTemp = tmp; ;
                    rList.Remove(i);
                }
            }
            return minTemp;
        }

        public int MinTaps(int n, int[] ranges)
        {
   
            //求区域
            int len = ranges.Length;
            int[,] r = new int[len,3];
            for(int i=0;i<len;i++)
            {
   
                r[i,0] = i - ranges[i];
                r[i, 1] = i + ranges[i];
                r[i, 2] = 1;//有效性
            }
            //求有效数据
            for (int i = 0; i < len; i++)
            {
   
                if(r[i,2] == 0) continue;
                for 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

放羊郎

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值