本文共 2602 字,大约阅读时间需要 8 分钟。
雨水收集问题是一道经典的算法题,目标是通过两个高度数组成的墙壁,计算能捕获的雨水总量。在本文中,我们将详细探讨两种高效解决方案:动态规划方法和双指针方法。
动态规划方法
动态规划是一种通过将问题分解成更小的子问题来解决复杂问题的方法。对于雨水收集问题,我们可以通过预先计算每个位置左边和右边的最大高度,来确定每个位置能捕获的雨水量。具体步骤如下:
left_max
和 right_max
,分别用于记录从左到右和从右到左的最大高度。left_max
数组:left_max[i]
表示从位置 0
到 i
之间的最大高度。right_max
数组:right_max[i]
表示从位置 i
到末尾之间的最大高度。i
,雨水量为 min(left_max[i], right_max[i]) - height[i]
,累加所有雨水量即可。这种方法的时间复杂度为 O(n),空间复杂度为 O(n),适用于处理较长的高度数组。
双指针方法是一种高效的两指针技术,常用于解决对称性较强的问题。本文将通过双指针方法来解决雨水收集问题。
双指针方法
双指针分别从数组的两端开始,向中间移动,比较当前位置的高度,确定哪一边的高度更高,然后计算当前位置能捕获的雨水量。具体步骤如下:
left
和 right
,分别指向数组的开头和末尾。left_max
和 right_max
,分别记录左边和右边的当前最大高度。ans
为 0。left_max
,则更新 left_max
。ans
。right_max
,则更新 right_max
。ans
。ans
。这种方法的时间复杂度为 O(n),空间复杂度为 O(1),实现更加高效,适用于处理较短的高度数组。
以下是两个方法的代码实现:
from typing import Listclass Solution: def trap(self, height: List[int]) -> int: if not height: return 0 ans = 0 size = len(height) left_max = [0] * size right_max = [0] * size # 从左到右计算最大值 left_max[0] = height[0] for i in range(1, size): left_max[i] = max(height[i], left_max[i-1]) # 从右到左计算最大值 right_max[size-1] = height[size-1] for i in range(size-2, -1, -1): right_max[i] = max(height[i], right_max[i+1]) # 计算雨水量 for i in range(1, size): ans += min(left_max[i], right_max[i]) - height[i] return ansprint(Solution().trap([4, 2, 0, 3, 2, 5]))
from typing import Listclass Solution: def trap(self, height: List[int]) -> int: if not height: return 0 ans = 0 size = len(height) left = 0 right = size - 1 left_max = 0 right_max = 0 while left < right: if height[left] < height[right]: if height[left] >= left_max: left_max = height[left] else: ans += left_max - height[left] left += 1 else: if height[right] >= right_max: right_max = height[right] else: ans += right_max - height[right] right -= 1 return ansprint(Solution().trap([4, 2, 0, 3, 2, 5]))
通过上述两种方法,我们可以高效地解决雨水收集问题。动态规划方法通过预先计算最大高度,确保每个位置的雨水量计算准确,而双指针方法则通过两指针技术,优化了空间复杂度,实现了更高效的解决方案。如果需要更深入的理解或优化,可以结合具体的应用场景选择最适合的方法。
转载地址:http://sfgfk.baihongyu.com/