最大矩形面积问题
问题描述
给定一个长度为 的序列 ,当我们选取任意 个相邻元素时,定义一种值
问最大的 值为多少。
暴力枚举做法
双重循环枚举最佳区间:
min(k * min(array[i : i + k]) for i in range(n - k))
时间复杂度 ,空间复杂度 。
单调栈做法
在python中,使用仅在末端插入和删除的数组来模拟栈。定义2个辅助数组left[]和right[],
先从左往右枚举,栈内维护自起点开始所有比当前值小的索引值,使left[i] = stack.top(),表示最近一个值小于array[i]的序列元素位置,right[]则从右往左进行一次同样的操作。
然后对序列内的每一个元素,计算以包含该元素且最小值为该元素的区间的 值,即为 (right[i] - left[i] - 1) * array[i]。
def solution(n, array):
# 初始化单调栈和左右扩展范围数组
stack = []
left = [0] * n
right = [0] * n
# 从左到右遍历数组,计算每个元素作为最小值时,能向左扩展的最大范围
for i in range(n):
while stack and array[stack[-1]] >= array[i]:
stack.pop()
left[i] = stack[-1] if stack else -1
stack.append(i)
stack = []
# 从右到左遍历数组,计算每个元素作为最小值时,能向右扩展的最大范围
for i in range(n-1, -1, -1):
while stack and array[stack[-1]] >= array[i]:
stack.pop()
right[i] = stack[-1] if stack else n
stack.append(i)
return max(array[i] * (right[i] - left[i] - 1) for i in range(n))
时间复杂度 ,空间复杂度 。
简单四则运算解析器
问题描述
小F面临一个编程挑战:实现一个基本的计算器来计算简单的字符串表达式的值。该字符串表达式有效,并可能包含数字(0-9)、运算符+、-及括号()。注意,字符串中不包含空格。除法运算应只保留整数结果。请实现一个解析器计算这些表达式的值,且不使用任何内置的eval函数。
做法
定义2个栈,nums和op,分别存放数字和操作。定义计算操作符的优先级,乘除优先级大于加减。从左到右扫描表达式,分类导论:
- 元素为数字:将其转换后压入
nums中 - 元素为左括号:将左括号压入
op中 - 元素为计算操作符:若当前操作符优先级低于
op栈顶的优先级,则先将nums栈顶2个数做计算,弹出op栈顶,再压入当前操作符;若当前操作符优先级高于或等于op栈顶的优先级,则直接压栈。 - 元素为右括号:不断取出
nums栈顶2个数做计算,并弹出op栈顶元素,直至栈顶为(时,再弹出。
最后还需要判断op栈内是否还有元素,若有则需要继续对nums栈顶2个数做计算,直到op栈空,nums栈唯一值为最终结果。
def solution(expression):
nums = []
op = []
n = len(expression)
pr = {'+':1, '-':1, '*':2, '/':2}
def ev():
a, b = nums[-1], nums[-2]
nums.pop()
nums.pop()
c = op[-1]
op.pop()
x = 0
if c == '+':
x = a + b
elif c == '-':
x = b - a
elif c == '*':
x = a * b
elif c == '/':
x = int(b / a)
nums.append(x)
for i in range(0, n):
if expression[i].isdigit():
nums.append(int(expression[i]))
elif expression[i] == '(':
op.append('(')
elif expression[i] == ')':
while op[-1] != '(':
ev()
op.pop()
else:
while len(op) > 0 and op[-1] != '(' and pr[op[-1]] >= pr[expression[i]]:
ev()
op.append(expression[i])
while len(op) > 0:
ev()
return nums[-1]
时间复杂度 ,空间复杂度 。
字符串解压缩
问题描述
小U拿到了一个通过特殊方式压缩的字符串,其中每个字母后面可能跟着一个数字,这个数字表示该字母在解压后的字符串中需要重复的次数。如果一个字母后面没有跟随数字,那么该字母在解压后的字符串中只出现一次。请帮助小U解压这个字符串并输出最终的解压结果。
做法
扫描字符串,分类导论:
- 元素为数字:从该元素位置开始继续往右查找依然为数字的元素,得到一个全部为数字的子区间,作为最近一个字母拷贝系数。
- 元素为字母:直接放入答案串。
def solution(s: str) -> str:
n = len(s)
i = 0
ret = []
while i<n:
if s[i].isdigit():
j = i
while j<n and s[j].isdigit():
j += 1
x = int(s[i:j])
ret[-1] = ret[-1]*x
i = j-1
else:
ret.append(s[i])
i+=1
return ''.join(ret)
时间复杂度 ,空间复杂度 。