当青训营遇上码上掘金

60 阅读2分钟

当青训营遇上码上掘金

1、题目分析

很明显,这就是leetcode上的接雨水题目,建议直接去上面找题解。。。

2、分析问题

在解决柱子接水问题时,我们可以采用以下思路:

  1. 遍历每一个柱子,找到其左右两侧的最高柱子。
  2. 如果左右两侧的最高柱子都高于当前柱子,则可以接住一定量的青豆。接住的数量取决于当前柱子高度与左右两侧最高柱子中较矮的一根柱子高度之差。
  3. 将每个柱子的接住的青豆数量加起来,即为整个柱子能接住的青豆数量。
def max_water(heights):
    n = len(heights)
    left_max = [0] * n
    right_max = [0] * n
    result = 0

    # 遍历每个柱子,找到其左侧最高柱子的高度
    left_max[0] = heights[0]
    for i in range(1, n):
        left_max[i] = max(left_max[i-1], heights[i])

    # 遍历每个柱子,找到其右侧最高柱子的高度
    right_max[n-1] = heights[n-1]
    for i in range(n-2, -1, -1):
        right_max[i] = max(right_max[i+1], heights[i])

    # 计算每个柱子能接住的青豆数量
    for i in range(n):
        water = min(left_max[i], right_max[i]) - heights[i]
        result += water if water > 0 else 0

    return result

该算法的时间复杂度为 O(n),空间复杂度也为 O(n)。算法时间复杂度较低,可以很好地处理大规模数据。

在使用该算法时,需要注意边角堆积问题。在计算每个柱子能接住的青豆数量时,需要确保左右两侧的最高柱子都高于当前柱子,才能接住青豆。因此,我们需要在计算左侧最高柱子和右侧最高柱子时,将第一个柱子和最后一个柱子排除在外,避免出现边角堆积问题。

3、其它解法

栈是一种先进后出(Last In First Out,LIFO)的数据结构。在这个问题中,我们可以使用一个栈来存储柱子的索引。遍历每个柱子时,如果栈为空或当前柱子高度小于等于栈顶柱子的高度,就将当前柱子的索引入栈。否则,弹出栈顶元素,计算能接住的青豆数量,并累加到结果中。遍历完所有柱子后,就可以得到最终的结果。

以下是使用栈解决柱子接水问题的算法实现:

def max_water_stack(heights):
    n = len(heights)
    stack = []
    result = 0

    for i in range(n):
        while stack and heights[i] > heights[stack[-1]]:
            top = stack.pop()
            if not stack:
                break
            distance = i - stack[-1] - 1
            water = min(heights[i], heights[stack[-1]]) - heights[top]
            result += distance * water

        stack.append(i)

    return result

使用栈解决这个问题的时间复杂度也为 O(n),空间复杂度为 O(n)。尽管两种算法的时间和空间复杂度相同,但是使用栈的算法更加简洁和直观。同时,在某些情况下,使用栈可能会更加高效,例如当柱子高度均匀分布时,使用栈的算法可以避免重复计算。