题解 | #四则运算#

四则运算

https://www.nowcoder.com/practice/9999764a61484d819056f807d2a91f1e

import sys


def cal(inp: str):
    # 先算括号,把所有括号都清除,从大括号到小括号
    for brace in ("{", "[", "("):
        if brace in inp:
            # 找到当前的第一对括号
            start, end = find_brace(inp, brace)
			# 递归计算括号内的结果,然后重新组装入参
            inp = inp[:start] + str(cal(inp[start + 1 : end])) + inp[end + 1 :]
			# 递归地得到结果
            return cal(inp)

    # 把去掉括号的字符串拆解成符号和数字,以列表形式存储,方便处理
    stack = devide_inp(inp)
	# 先计算乘除法,因为优先级更高
    stack = cal_multi(stack)
	# 最后计算加减法
    res = cal_plus(stack)
    return int(res)


def find_brace(inp, brace):
    """找到字符串inp的brace括号的第一个完整的括号序号"""
    start, end = None, None
	# 因为可能有重叠的括号,需要找到完整括号内的内容
    brace_stack = []
    brace_map = {"{": "}", "[": "]", "(": ")"}
    for i, each in enumerate(inp):
        if each == brace:
            brace_stack.append(brace)
            if start is None:
                start = i
        elif each == brace_map[brace]:
            brace_stack.pop()
            if not brace_stack:
                end = i
                break

    return start, end


def devide_inp(inp: str):
    """把输入的字符串拆解成符号与数字"""
    start, end = 0, 0
    stack = []
    for i, each in enumerate(inp):
        if each not in ("+", "-", "*", "/"):
            continue
        end = i
        # 拆分的时候注意负数的计算,如果两种符号连着的,就把负号也带上
        if each == "-" and end - start == 0:
            continue

        stack.append(float(inp[start:end]))
        stack.append(each)
        start = i + 1

    stack.append(float(inp[start:]))
    return stack


def cal_multi(stack: list):
    # 处理乘除的计算,直到再也找不到
	# 从后往前处理,可以避免stack处理后,其后的序号出现变化的问题
    for i in range(len(stack)-2, 0, -2):
        if stack[i] not in ("*", "/"):
            continue

        if stack[i] == "*":
            stack[i-1] *= stack[i+1]
            stack.pop(i)
            stack.pop(i)
        else:
            stack[i-1] *= stack[i+1]
            stack.pop(i)
            stack.pop(i)

    return stack


def cal_plus(stack: list):
    # 处理加减
    while len(stack) > 1:
        if stack[1] == "+":
            stack[0] += stack[2]
            stack.pop(1)
            stack.pop(1)
        elif stack[1] == "-":
            stack[0] -= stack[2]
            stack.pop(1)
            stack.pop(1)
    return stack[0]




for line in sys.stdin:
    print(cal(line))
	
	# 以下用Python的eval即可解决
    # line = line.replace("[", "(")
    # line = line.replace("]", ")")
    # line = line.replace("{", "(")
    # line = line.replace("}", ")")
    # print(int(eval(line)))



全部评论

相关推荐

自从我室友在计算机导论课上听说了“刷 LeetCode 是进入大厂的敲门砖”,整个人就跟走火入魔了一样。他在宿舍门口贴了一张A4纸,上面写着:“正在 DP,请勿打扰,否则 Time Limit Exceeded。”日记本的扉页被他用黑色水笔加粗描了三遍:“Talk is cheap. Show me the code。”连宿舍聚餐,他都要给我们讲解:“今天的座位安排可以用回溯算法解决,但为了避免栈溢出,我建议用动态规划。来,这是状态转移方程:dp[i][j] 代表第 i 个人坐在第 j 个位置的最优解。”我让他去楼下取个快递,他不直接去,非要在门口踱步,嘴里念念有词:“这是一个图的遍历问题。从宿舍楼(root)到驿站(target node),我应该用 BFS 还是 DFS?嗯,求最短路径,还是广度优先好。”和同学约好出去开黑,他会提前发消息:“集合点 (x, y),我们俩的路径有 k 个交点,为了最小化时间复杂度,应该在 (x/2, y/2) 处汇合。”有一次另一个室友低血糖犯了,让他帮忙找颗糖,他居然冷静地分析道:“别急,这是一个查找问题。零食箱是无序数组,暴力查找是 O(n)。如果按甜度排序,我就可以用二分查找,时间复杂度降到 O(log n)。”他做卫生也要讲究算法效率:“拖地是典型的岛屿问题,要先把连通的污渍区块都清理掉。倒垃圾可以用双指针法,一个指针从左往右,一个从右往左,能最快匹配垃圾分类。”现在我们宿舍的画风已经完全变了,大家不聊游戏和妹子,对话都是这样的:“你 Two Sum 刷了几遍了?”“别提了,昨天遇到一道 Hard 题,我连暴力解都想不出来,最后只能看题解。你呢?”“我动态规划还不行,总是找不到最优子结构。今天那道接雨水给我整麻了。”……LeetCode 真的害了我室友!!!
老六f:编程嘉豪来了
AI时代还有必要刷lee...
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务