【基础算法精讲 02】盛最多水的容器 接雨水

7 阅读3分钟

一刷略过:2026/01/17

二刷:2026/01/18

题目:11. 盛最多水的容器

解法:

双指针,头尾两端遍历,s = max(ans, s) & s = min(height[left], height[right]) * (right - left)

时间复杂度:O(n)
空间复杂度:O(1)

代码实现:

class Solution:
    def maxArea(self, height: List[int]) -> int:
        n = len(height)
        ans = 0
        left = 0
        right = n - 1
        while left < right:
            s = min(height[left], height[right]) * (right - left)
            ans = max(ans, s)
            if height[left] < height[right]:
                left += 1
            else:
                right -= 1
        return ans

题目:42. 接雨水

解法一:

定义两个数组,从0→n-1正向遍历一次,将左侧最大柱高写入数组中,目的是表示当前索引下左侧最大柱高是多少;同理,反向遍历将当前柱高右侧最大柱高写入数组中,后遍历一次即可记录当前数组左右最大柱高分别是多少?选择较小的与当前柱高相减,就得到当前柱子可以装入的最大雨水量。

时间复杂度:O(n)
空间复杂度:O(n)

代码实现:

解法一:
class Solution:
    def trap(self, height: List[int]) -> int:
        # 定义两个数组分别装入该索引下左右两个最高柱高,较矮的与该柱高之差即为当前索引可接纳的水
        n = len(height)
        pre_max = [0] * n
        pre_max[0] = height[0]
        for i in range(1, n):
            pre_max[i] = max(pre_max[i - 1], height[i])
        aft_max = [0] * n
        aft_max[-1] = height[-1]
        for i in range(n - 2, -1, -1):
            aft_max[i] = max(aft_max[i + 1], height[i])
        ans = 0
        for h, pre, aft in zip(height, pre_max, aft_max):
            ans += min(pre, aft) - h # "min(pre, aft) - h"不可能为负数,因为最小值为其自身高度
        return ans

解法二:双指针,相比于第一种优化的空间复杂度,O(n)→O(1)

时间复杂度:O(n)
空间复杂度:O(1)
class Solution:
    def trap(self, height: List[int]) -> int:
        # 双指针
        # 定义左右两个指针,分别表示左右最高柱高,随着循环的进行随时做更新,同时结果也做更新
        n = len(height)
        left, right = 0, n - 1
        ans = pre_max = aft_max = 0
        while left < right:
            # 更新左右最大柱高
            pre_max = max(pre_max, height[left])
            aft_max = max(aft_max, height[right])
            if pre_max < aft_max:
                # 更新结果
                ans += pre_max - height[left]
                left += 1
            else:
                # 更新结果
                ans += aft_max - height[right]
                right -= 1
        return ans

练习题一刷:2026/01/18

题目:125. 验证回文串

解法

双指针,两侧遍历判断字符是否有效,无效则跳过,有效则判断是否相等,相等则向内收敛,持续循环,不相等则返回False,如果可以执行到最后返回True.

时间复杂度:O(n)
空间复杂度:O(1)
class Solution:
    def isPalindrome(self, s: str) -> bool:
        # 双指针判断是否有效,无效直接向内收敛,
        # 有效则判断是否相等,相等持续循环 向内收敛,否则跳出循环返回False
        # 如果可以执行到最后,说明s呈现对称性
        left, right = 0, len(s) - 1
        while left < right:
            if not s[left].isalnum():
                left += 1
            elif not s[right].isalnum():
                right -= 1
            elif s[left].lower() == s[right].lower():
                left += 1
                right -= 1
            else:
                return False
        return True

题目:2105. 给植物浇水 II

解法:双指针

时间复杂度:O(n)
空间复杂度:O(1)
class Solution:
    def minimumRefill(self, plants: List[int], capacityA: int, capacityB: int) -> int:
        a, b = capacityA, capacityB
        i, j = 0, len(plants) - 1
        ans = 0
        while i < j:
            # Alice 从前往后浇水
            # 若水少则加水,否则直接往下浇水
            if a < plants[i]:
                ans += 1
                a = capacityA
            a -= plants[i]
            i += 1
            # Bob 从后往前浇水
            if b < plants[j]:
                ans += 1
                b = capacityB
            b -= plants[j]
            j -= 1
            # 剩下最后一个时,用水多的判断是否足够,不够则加水1次
            if i == j and max(a, b) < plants[i]:
                ans += 1
        return ans