今天不知道为什么 好困
什么时候要用到栈呢,真的搞不太清楚,先上题
6.30 求最大矩形面积
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
先给出简单解法:
依次遍历每一个矩阵宽度,找到这个宽度的边界。
比如:
对于height[0] = 2,我们找到它的边界是左0右0,面积是1;
对于height[2] = 5,我们找到它的边界是左2右3,面积是2。
但时间复杂度是 O ( n 2 ) O(n^2) O(n2)
其实我们思考一下,找边界的问题,就是找到左/右边第一个没它高的height,然后停止!这类“在一维数组中找第一个满足某种条件的数”的场景就是典型的单调栈应用场景。
我们希望只经过一次遍历就找到每一个height的左右边界,OK,那么元素从左到右依次进栈。
如何找左边界?——元素height进栈前,把栈内大于height的元素依次弹出,现在的栈顶元素的index就是第一个比它小的。(+1就是左边界)
如何找右边界?——元素height出栈的时候,当前遍历的index就是第一个比它小的(-1就是右边界)(因为当前的h[index] < height才导致出栈 )
有一种特殊情况,可能有的元素不会出栈,如[1,2,3,4,5],这个时候我们初始右边界为n - 1
一定要好好细品!
class Solution:
def largestRectangleArea(self, heights: List[int]) -> int:
n, stack = len(heights), []
left, right = [0] * n, [n - 1] * n
area = 0
for i in range(n):
while (stack and heights[i] <= heights[stack[-1]]):
index = stack[-1]
stack.pop()
right[index] = i - 1
left[i] = stack[-1] + 1 if stack else 0
stack.append(i)
area = max((right[i] - left[i] + 1) * heights[i] for i in range(n)) if n > 0 else 0
return area
附上代码,这个代码栈存的是index而不是height,因为height更容易访问。
百度笔试第三题 走矩阵
给定一个字符矩阵,矩阵仅由’r’,‘e’,'d’组成。
求从左上角到右下角的最少步数。可以从上下左右四个方向走,但是不能从’r’->‘d’, ‘e’->‘r’,‘d’->‘e’。
第一行输入n m (1<n,m<500)
n表示矩阵的行 m表示矩阵的列
接下来n行 输入一个长为m的”red”字符串
“red”字符串是指所有字符均为”r"或”e"或”d”
你可以在矩阵中上下左右移动
但是r不能移动到d e不能移动到r d不能移动到e
输出从左上角走到右下角最少需要多长时间
如无法到达输出-1
其实这种走迷宫的题很多,我之前用的都是回溯或者dp,但这题不太能用这两个方法,因为:
①回溯的是时间复杂度太高了
②dp一般设置为只能往右或往下。这种题的路径可能会绕过来(因为有的路径是不通的!)
所以题解用到了队列,这样的好处就是能够任意行动,而且每个格子只记录第一次到的时间(初始的时间设置为一个大数)
from collections import deque
ban = "rderde"
mp = {}
for i in range(0, 5, 2):
mp[ban[i + 1]] = ban[i]
n, m = map(int, input().split())
board = []
for _ in range(n):
s = list(input().strip())
board.append(s)
inf = 10 ** 9
q = deque([(n - 1, m - 1)])
g = [[inf] * m for _ in range(n)]
g[n - 1][m - 1] = 0
while q:
x, y = q.popleft()
for dx, dy in [(0, -1), (0, 1), (1, 0), (-1, 0)]:
nx, ny = dx + x, dy + y
if (
0 <= nx < n
and 0 <= ny < m
and mp[board[x][y]] != board[nx][ny]
and g[nx][ny] == inf
):
g[nx][ny] = g[x][y] + 1
q.append((nx, ny))
if g[0][0] == inf:
print(-1)
else:
print(g[0][0])
这里从终点走到了起点(不知道为什么这么设计…)
用了一个字典来告诉我们x禁止走向y
注意还有一个for dx,dy in[(),(),(),()]:
这个用法挺常见的,记录一下。