Leetcode2086. 从房屋收集雨水需要的最少水桶数

Every day a Leetcode

题目来源:2086. 从房屋收集雨水需要的最少水桶数

解法1:贪心

我们可以对字符串 hamsters 从左到右进行一次遍历。

每当我们遍历到一个房屋时,我们可以有如下的选择:

  • 如果房屋的两侧已经有水桶,那么我们无需再放置水桶了;

  • 如果房屋的两侧没有水桶,那么我们优先在房屋的「右侧」放置水桶,这是因为我们是从左到右进行遍历的,即当我们遍历到第 i 个位置时,前 i−1 个位置的房屋周围都是有水桶的。因此我们在左侧放置水桶没有任何意义,而在右侧放置水桶可以让之后的房屋使用该水桶。

  • 如果房屋的右侧无法放置水桶(例如是另一栋房屋或者边界),那么我们只能在左侧放置水桶。如果左侧也不能放置,说明无解。

我们可以通过修改字符串来表示水桶的放置,从而实现上述算法。一种无需修改字符串的方法是,每当我们在房屋的右侧放置水桶时,可以直接「跳过」后续的两个位置,因为如果字符串形如 H.H,我们在第一栋房屋的右侧(即两栋房屋的中间)放置水桶后,就无需考虑第二栋房屋;如果字符串形如 H...,后续没有房屋,我们也可以全部跳过。

代码:

c 复制代码
/*
 * @lc app=leetcode.cn id=2086 lang=cpp
 *
 * [2086] 从房屋收集雨水需要的最少水桶数
 */

// @lc code=start
class Solution
{
public:
    int minimumBuckets(string hamsters)
    {
        int n = hamsters.size();
        int bucket = 0;
        for (int i = 0; i < n; i++)
        {
            if (hamsters[i] == 'H')
            {
                if (i + 1 < n && hamsters[i + 1] == '.')
                {
                    bucket++;
                    i += 2;
                }
                else if (i - 1 >= 0 && hamsters[i - 1] == '.')
                    bucket++;
                else
                    return -1;
            }
        }
        return bucket;
    }
};
// @lc code=end

结果:

复杂度分析:

时间复杂度:O(n),其中 n 是字符串 hamsters 的长度。

空间复杂度:O(1)。

解法2:动态规划

设遍历至前 i 个字符满足条件的最小水桶数为 dp[i]。

若 street[i - 1] 为 '.':

  • 不放置水桶。此时有
  • 若前面一个为房屋(street[i - 2] == 'H'),可放置水桶。此时有

else if street[i - 1] 为 'H':

  • 前方必须放置水桶,则必须满足 street[i - 2] == '.'。此时有
  • 上一个条件满足情况下如果水桶前方是房子(street[i - 3] == 'H'),则这个水桶也可以接到前面房子的水。此时有

所有的状态转移取最小值即可。

代码:

c 复制代码
/*
 * @lc app=leetcode.cn id=2086 lang=cpp
 *
 * [2086] 从房屋收集雨水需要的最少水桶数
 */

// @lc code=start

// 贪心

// class Solution
// {
// public:
//     int minimumBuckets(string hamsters)
//     {
//         int n = hamsters.size();
//         int bucket = 0;
//         for (int i = 0; i < n; i++)
//         {
//             if (hamsters[i] == 'H')
//             {
//                 if (i + 1 < n && hamsters[i + 1] == '.')
//                 {
//                     bucket++;
//                     i += 2;
//                 }
//                 else if (i - 1 >= 0 && hamsters[i - 1] == '.')
//                     bucket++;
//                 else
//                     return -1;
//             }
//         }
//         return bucket;
//     }
// };

class Solution
{
private:
#define INF 0x3F3F3F3F
#define MAX_LEN 1e5 + 10

public:
    int minimumBuckets(string street)
    {
        int n = street.size();
        vector<int> dp(MAX_LEN, INF);
        // 初始化
        dp[0] = 0;
        // 状态转移
        for (int i = 1; i <= n; i++)
        {
            if (street[i - 1] == '.')
            {
                dp[i] = dp[i - 1];
                if (i - 2 >= 0 && street[i - 2] == 'H')
                    dp[i] = min(dp[i], dp[i - 2] + 1);
            }
            else if (street[i - 1] == 'H')
            {
                if (i - 2 >= 0 && street[i - 2] == '.')
                {
                    dp[i] = dp[i - 2] + 1;
                    if (i - 3 >= 0 && street[i - 3] == 'H')
                    {
                        dp[i] = min(dp[i], dp[i - 3] + 1);
                    }
                }
            }
        }
        return dp[n] >= INF ? -1 : dp[n];
    }
};
// @lc code=end

结果:

复杂度分析:

时间复杂度:O(n),其中 n 是字符串 street 的长度。

空间复杂度:O(MAX_LEN)。状态数组开销,MAX_LEN = 1e5 + 10。

相关推荐
野渡拾光2 分钟前
【考研408数据结构-05】 串与KMP算法:模式匹配的艺术
数据结构·考研·算法
tainshuai2 小时前
用 KNN 算法解锁分类的奥秘:从电影类型到鸢尾花开
算法·分类·数据挖掘
Coovally AI模型快速验证8 小时前
农田扫描提速37%!基于检测置信度的无人机“智能抽查”路径规划,Coovally一键加速模型落地
深度学习·算法·yolo·计算机视觉·transformer·无人机
pusue_the_sun8 小时前
数据结构:二叉树oj练习
c语言·数据结构·算法·二叉树
RaymondZhao349 小时前
【全面推导】策略梯度算法:公式、偏差方差与进化
人工智能·深度学习·算法·机器学习·chatgpt
zhangfeng11339 小时前
DBSCAN算法详解和参数优化,基于密度的空间聚类算法,特别擅长处理不规则形状的聚类和噪声数据
算法·机器学习·聚类
圣保罗的大教堂10 小时前
leetcode 2348. 全 0 子数组的数目 中等
leetcode
啊阿狸不会拉杆10 小时前
《算法导论》第 32 章 - 字符串匹配
开发语言·c++·算法
小学生的信奥之路10 小时前
洛谷P3817题解:贪心算法解决糖果分配问题
c++·算法·贪心算法
你知道网上冲浪吗11 小时前
【原创理论】Stochastic Coupled Dyadic System (SCDS):一个用于两性关系动力学建模的随机耦合系统框架
python·算法·数学建模·数值分析