leetcode
leetcode 651 ~ 700
倒水

倒水

难度:

标签:

题目描述

代码结果

运行时间: 40 ms, 内存: 0.0 MB


/*
 * LeetCode题目: 倒水
 * 
 * 题目思路: 
 * 给定一个整数数组`buckets`,其中每个元素表示一个水桶的容量。
 * 需要找到在给定的最大倒水次数`pours`内,是否可以将所有的水桶都倒满。
 * 
 * 解题步骤:
 * 1. 使用Stream对水桶容量数组`buckets`进行排序。
 * 2. 使用Stream计算倒水总容量`totalCapacity`。
 * 3. 通过最大倒水次数`pours`来判断是否能满足所有水桶倒满。
 * 
 */

import java.util.Arrays;
import java.util.stream.IntStream;

public class WaterPouringStream {
    public boolean canFillAllBuckets(int[] buckets, int pours) {
        int totalCapacity = Arrays.stream(buckets)  // 步骤1: 使用Stream对水桶容量数组进行排序
                                  .sorted()
                                  .sum();          // 步骤2: 使用Stream计算倒水总容量
        return pours >= totalCapacity;  // 步骤3: 判断最大倒水次数是否满足
    }

    public static void main(String[] args) {
        WaterPouringStream wp = new WaterPouringStream();
        int[] buckets = {2, 3, 5};
        int pours = 10;
        boolean result = wp.canFillAllBuckets(buckets, pours);
        System.out.println(result);  // 输出: true
    }
}

解释

方法:

该题解采用了模拟倒水的过程,使用了两个单调栈分别记录倒水过程中左右两侧的可倒水的低洼位置。具体思路如下: 1. 首先利用 findLeft 和 findRight 两个函数分别找出初始位置 K 左右两侧的所有可倒水的低洼位置,并分别存入 leftStack 和 rightStack 中。 2. 开始模拟倒水过程,总共倒 V 次水: - 如果 leftStack 非空,则将水倒在 leftStack 的栈顶位置,并更新该位置的高度。如果该位置已经不再是低洼,则将其从 leftStack 中弹出。然后检查其左侧相邻位置是否因为高度改变而成为新的低洼,如果是则将其加入 leftStack。 - 如果 leftStack 为空但 rightStack 非空,则将水倒在 rightStack 的栈顶位置,并更新该位置的高度。如果该位置已经不再是低洼,则将其从 rightStack 中弹出。然后检查其右侧相邻位置是否因为高度改变而成为新的低洼,如果是则将其加入 rightStack。 - 如果 leftStack 和 rightStack 均为空,则将水倒在初始位置 K 上,并更新 K 位置的高度。然后重新调用 findLeft 和 findRight 函数更新 leftStack 和 rightStack。 3. 倒完 V 次水后,返回更新后的高度数组 heights 即可。

时间复杂度:

O(V*n)

空间复杂度:

O(n)

代码细节讲解

🦆
在模拟倒水的过程中,如果同时左右两侧栈均非空,你是如何决定优先倒水到左侧还是右侧的?
在题解中,如果左右两侧的单调栈均非空时,优先倒水到左侧。这是基于一个常见的倒水模拟原则,即优先填充左侧的低洼位置。这种选择可能是为了模拟自然界中水流由高处向低处流动的趋势,通常左侧的低洼位置在空间位置上更接近倒水初始点的左侧,因此先进行处理。这也可以视为一种设计选择,以保持算法的一致性和可预测性。
🦆
当左或右侧的单调栈为空时,你是如何确保继续倒水操作不会导致非最低点被选择的?
当左或右侧的单调栈为空时,若另一侧的栈仍然非空,则会继续在非空的那侧的栈顶位置进行倒水。这保证了水总是被倒在当前可识别的最低洼位置。如果两个栈都为空,水会被倒在初始位置K上。在倒水之后,会重新评估并更新左右两侧的单调栈,确保接下来的倒水仍然是在最低点进行。这种机制确保了倒水操作始终聚焦于当前的最低位置或潜在的新低洼位置。
🦆
在更新高度信息后,你是如何判断并处理位置变为非低洼的情况?特别是在复杂的地形变化中。
在每次倒水后,会检查倒水位置的新高度是否还符合低洼位置的条件。如果该位置的高度不再低于其相邻位置,这个位置就会从单调栈中被移除,表示它不再是一个低洼位置。同时,会检查该位置的相邻位置是否因为高度的改变而变成新的低洼地形。如果是,这些新的低洼位置将被加入到相应的单调栈中。这个动态更新过程帮助算法适应复杂的地形变化,并确保始终能够在最低的可用位置进行倒水操作。
🦆
当你说如果 '左右均无低洼位置,则将水倒在初始位置 K',这种情况下如何处理 K 位置周围可能产生的新低洼位置?
当左右均无低洼位置,且水被倒在初始位置K后,会立即调用findLeft和findRight函数重新检查K位置左右两侧是否由于K位置高度的改变而产生新的低洼位置。如果检测到新的低洼位置,这些位置会被加入到相应的单调栈中。这确保了即使在初始位置K周围由于倒水导致地形变化,算法也能及时识别并处理新产生的低洼位置,维持倒水过程的正确性和效率。

相关问题

接雨水

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

 

示例 1:

输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 

示例 2:

输入:height = [4,2,0,3,2,5]
输出:9

 

提示:

  • n == height.length
  • 1 <= n <= 2 * 104
  • 0 <= height[i] <= 105