逆波兰表达式解法:牛客网 HJ70 矩阵乘法计算量估算

描述

矩阵乘法的运算量与矩阵乘法的顺序强相关。
例如:

A是一个50×10的矩阵,B是10×20的矩阵,C是20×5的矩阵

计算ABC有两种顺序:((AB)C)或者(A(BC)),前者需要计算15000次乘法,后者只需要3500次。
编写程序计算不同的计算顺序需要进行的乘法次数。

数据范围:矩阵个数:1≤n≤15 1≤n≤15 ,行列数:1≤rowi,coli≤100 1≤rowi​,coli​≤100 ,保证给出的字符串表示的计算顺序唯一。
进阶:时间复杂度:O(n) O(n) ,空间复杂度:O(n) O(n)

输入描述:
输入多行,先输入要计算乘法的矩阵个数n,每个矩阵的行数,列数,总共2n的数,最后输入要计算的法则
计算的法则为一个字符串,仅由左右括号和大写字母(‘A’~‘Z’)组成,保证括号是匹配的且输入合法!
输出描述:
输出需要进行的乘法次数

示例1
输入:
3
50 10
10 20
20 5
(A(BC))
输出:
3500

逆波兰表达式的生成

参考:https://www.cnblogs.com/feika/p/3607431.html

普通表达式一般由数字、变量与±*/()运算符号组成。

例如:
(a+b)*3 - (a-b)/2

其逆波兰表达式是: a b + 3 * a b - 2 / -

本质上,普通表达式是中序表达式,逆波兰表达式是后序表达式。

一)、由普通表达式生成逆波兰表达式

1、初始化1个逆波兰字符串变量outstr,以及1个符号栈;自左向右输入表达式串; 2、如果当前字符为数值或变量,则直接添加到逆波兰字符串后 outstr;

3、如果当前字符为运算符号,如果是“(”,则直接压入符号栈;如果是“)”,则从栈中逐项pop运算符号,追加在outstr后;如果是其他运算符号,比较当前与栈顶的运算符优先级,如果当前低,则pop栈顶运算符,压入当前运算符号;如果当前的高,则直接压入栈中;

4、遇到结束符号时,逐项从栈中pop运算符项;

二)、计算逆波兰表达式的值

1、自左向右输入逆波兰表达式串;

2、如果当前为操作数,则直接压入栈;

3、如果当前为运算符号,则从栈顶两个进行计算,并将计算结果压入栈中;

4、最后从栈中pop出最终运算结果。

代码

# 逆波兰表达式法
def getPrefixExpression(exp_str):
    prefix_exp_str = ""
    ope_stack = []
    last_ope = ""
    for ope_ in exp_str:
        if(ope_ == "("):
            if(last_ope != "("): ope_stack.append('*')
            ope_stack.append(ope_)
        elif(ope_ == ")"):
            while(ope_stack[-1]!="("):
                prefix_exp_str += ope_stack.pop()
            ope_stack.pop()
        else:
            if(last_ope != "("): ope_stack.append('*')
            prefix_exp_str += ope_
        last_ope = ope_

    return prefix_exp_str

def getMultiplyFre(mats_info,exp_str):
    prefix_exp_str = getPrefixExpression(exp_str)
    #print(prefix_exp_str)
    data_stack = []
    multiply_cnt = 0
    for ope_ in prefix_exp_str:
        if(ope_!= "*"):
            data_stack.append(mats_info.pop(0))
        else:
            mat2 = data_stack.pop()
            mat1 = data_stack.pop()
            res_mat,multiply_fre = matMultiply(mat1,mat2)
            multiply_cnt += multiply_fre
            data_stack.append(res_mat)

    return multiply_cnt

def matMultiply(mat1,mat2):
    res_mat = [mat1[0],mat2[1]]
    multiply_fre = mat1[0]*mat1[1]*mat2[1]
    return res_mat,multiply_fre

# 怎么这么多括号题
mat_num = int(input())
mats_info = []
for i in range(mat_num): mats_info.append(list(map(int,input().split())))
exp_str = list(input())
mulitply_fre = getMultiplyFre(mats_info,exp_str)
print(mulitply_fre)

传统算中缀表达式的解法:

def getMultiplyFre(mats_info,exp_str):
    data_stack = []
    ope_stack = []
    multiply_cnt = 0
    while(exp_str):
        ope_str = exp_str.pop(0)
        if(ope_str == "("):
            ope_stack.append(ope_str)
        elif(ope_str == ")"):
            temp_data_stack = []
            while(True):
                ope_str = ope_stack.pop()
                if(ope_str == "("): break
                temp_data_stack.append(data_stack.pop())
            if(temp_data_stack):
                while(len(temp_data_stack)!=1):
                    mat1 = temp_data_stack.pop()
                    mat2 = temp_data_stack.pop()
                    res_mat,multiply_fre = matMultiply(mat1,mat2)
                    multiply_cnt += multiply_fre
                    temp_data_stack.append(res_mat)
                data_stack.append(temp_data_stack.pop())
                ope_stack.append("*")

        else:
            data_stack.append(mats_info.pop(0))
            ope_stack.append("*")
            
    return multiply_cnt

def matMultiply(mat1,mat2):
    res_mat = [mat1[0],mat2[1]]
    multiply_fre = mat1[0]*mat1[1]*mat2[1]
    return res_mat,multiply_fre

# 怎么这么多括号题
mat_num = int(input())
mats_info = []
for i in range(mat_num): mats_info.append(list(map(int,input().split())))
exp_str = list(input())
mulitply_fre = getMultiplyFre(mats_info,exp_str)
print(mulitply_fre)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值