AI刷题记录(一) | 豆包MarsCode AI刷题

69 阅读1分钟

最大矩形面积问题

问题描述

给定一个长度为 nn 的序列 h1,h2,,hnh_1, h_2, \dots, h_n,当我们选取任意 kk 个相邻元素时,定义一种值

R(k)=k×min{hi,hi+1,,hi+k1},1ink+1R(k)=k\times\min\{h_i,h_{i+1},\dots,h_{i+k-1}\},\quad 1\le i\le n-k+1

问最大的 R(k)R(k) 值为多少。

暴力枚举做法

双重循环枚举最佳区间:

min(k * min(array[i : i + k]) for i in range(n - k))

时间复杂度 O(n2)\text{O}(n^2) ,空间复杂度 O(n)\text{O}(n)

单调栈做法

在python中,使用仅在末端插入和删除的数组来模拟栈。定义2个辅助数组left[]right[]

先从左往右枚举,栈内维护自起点开始所有比当前值小的索引值,使left[i] = stack.top(),表示最近一个值小于array[i]的序列元素位置,right[]则从右往左进行一次同样的操作。

然后对序列内的每一个元素,计算以包含该元素且最小值为该元素的区间的 RR 值,即为 (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))

时间复杂度 O(n)\text{O}(n) ,空间复杂度 O(n)\text{O}(n)

简单四则运算解析器

问题描述

小F面临一个编程挑战:实现一个基本的计算器来计算简单的字符串表达式的值。该字符串表达式有效,并可能包含数字(0-9)、运算符+-及括号()。注意,字符串中不包含空格。除法运算应只保留整数结果。请实现一个解析器计算这些表达式的值,且不使用任何内置的eval函数。

做法

定义2个栈,numsop,分别存放数字和操作。定义计算操作符的优先级,乘除优先级大于加减。从左到右扫描表达式,分类导论:

  • 元素为数字:将其转换后压入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]

时间复杂度 O(n)\text{O}(n) ,空间复杂度 O(n)\text{O}(n)

字符串解压缩

问题描述

小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)

时间复杂度 O(n)\text{O}(n) ,空间复杂度 O(n)\text{O}(n)