单调栈、构造法、two pointers,LeetCode 42 题多种解法深入剖析
2023-10-10 13:15:13
应对 LeetCode 42 题:三种巧妙解法
前言
LeetCode 42 题是算法和数据结构的严峻考验,它要求您计算水坝中可容纳的水量。在这篇博客中,我们将探索三种不同的解法:单调栈、构造法和 Two Pointers,并深入了解它们的机制和优缺点。
单调栈解法
想象一个栈,按照水坝高度递增排列。当遇到一个比栈顶更高的水坝时,就可以计算出它能容纳的水量。我们从左到右遍历水坝,不断更新栈顶元素并计算水量。
def trap(heights):
stack = []
total_water = 0
for i, height in enumerate(heights):
while stack and height > heights[stack[-1]]:
top = stack.pop()
if not stack:
break
distance = i - stack[-1] - 1
water = distance * min(heights[stack[-1]], height)
total_water += water
stack.append(i)
return total_water
构造法解法
另一种方法是逐步构造解决方案。我们从左到右遍历水坝,跟踪左、右边界以及最高水坝的高度。当遇到一个较高的水坝时,我们计算左边界和右边界之间的水量。
def trap(heights):
left = 0
right = 0
max_height = 0
total_water = 0
for i, height in enumerate(heights):
if height > max_height:
left = i
max_height = height
elif height >= heights[right]:
right = i
if right > left:
water = min(heights[left], heights[right]) - height
total_water += water
return total_water
Two Pointers 解法
这种方法使用两个指针:left 和 right。它们从数组两端向内移动。当 left 指向的水坝高度较低时,它向右移动。当 right 指向的水坝高度较高时,它向左移动。当两个指针相遇时,我们计算它们之间的水量。
def trap(heights):
left = 0
right = len(heights) - 1
total_water = 0
while left < right:
if heights[left] < heights[right]:
left += 1
water = min(heights[left], heights[right]) - heights[left]
total_water += water
else:
right -= 1
water = min(heights[left], heights[right]) - heights[right]
total_water += water
return total_water
比较与总结
这三种方法各有优势:
- 单调栈:易于理解,适合水坝高度较少的情况。
- 构造法:灵活,适用于各种水坝高度分布。
- Two Pointers:效率较高,适用于水坝高度较多的情况。
选择哪种方法取决于具体问题。
常见问题解答
- 哪种解法最有效率?
在平均情况下,这三种解法都为 O(n)。然而,在最坏情况下,单调栈和构造法为 O(n^2),而 Two Pointers 为 O(n)。
- 哪种解法最容易理解?
单调栈解法相对简单,易于理解和实现。
- 我可以使用动态规划解决这个问题吗?
虽然动态规划可以解决此问题,但它不如这里讨论的解法那么有效。
- 如何优化这些解法?
使用空间优化技术,如原地算法,可以减少空间复杂度。
- LeetCode 42 题的难度如何?
LeetCode 42 题被评为 "Hard" 难度,需要扎实的算法和数据结构知识。
总结
LeetCode 42 题是一个极具挑战性的问题,它考验了您的算法和数据结构技能。通过了解单调栈、构造法和 Two Pointers 等多种解法,您将能够解决这类问题并提升您的 LeetCode 技巧。记住,选择最佳解法取决于特定问题,不断练习和探索将帮助您成为一名更好的算法大师。