逆波兰表达式解法:牛客网 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
    评论
### 回答1: MATLAB微分方程高效解法:谱方法原理与实现 谱方法是一种高效解法,用于解决微分方程。它是基于微分方程在频域上的表示和计算,具有较高的精度和数值稳定性。以下介绍MATLAB中的谱方法原理及其实现。 谱方法基于傅里叶级数将微分方程在频域上进行展开,并利用傅里叶变换进行相关运算。首先,将微分方程的解表示为一组基函数的线性组合,并确定这些基函数的权重。常用的基函数包括正弦函数和余弦函数。然后,通过将微分方程代入基函数的线性组合中,并利用傅里叶级数展开的性质,将微分方程转化为频域上的代数方程组。最后,利用傅里叶反变换将频域上的解转换回时域上。 在MATLAB中,可以利用fft函数进行快速傅里叶变换和ifft函数进行快速傅里叶反变换。通过将微分方程转化为频域上的代数方程组,可以构建一个矩阵方程。利用MATLAB中的线性代数工具箱,可以求解这个矩阵方程并得到微分方程的数值解。此外,通过选择合适的基函数和调整基函数的权重,可以提高数值解的精度和稳定性。 谱方法在求解偏微分方程和时变微分方程等复杂问题上具有很大的优势。它能够得到高精度的数值解,并且可以处理高维问题和非线性问题。然而,谱方法在计算和存储需求上比较大,对计算资源有一定要求。因此,在实际应用中需要根据问题的特点和计算资源的限制进行选择。 总之,MATLAB提供了丰富的工具和函数来实现谱方法,用于高效解决微分方程。通过合理选择基函数和权重,并借助傅里叶变换和矩阵求解方法,可以得到精确的数值解。谱方法在科学计算和工程应用中具有广泛的应用前景。 ### 回答2: MATLAB微分方程高效解法: 谱方法原理与实现PDF 是一本介绍利用谱方法解决微分方程的PDF教材。谱方法是求解微分方程的一种有效方法,它基于傅里叶级数展开和谱逼近的原理,能够得到高精度的数值解。 首先,谱方法利用傅里叶级数展开将微分方程转化为代数方程组,通过求解方程组得到数值解。傅里叶级数展开能够将周期函数分解成多个正弦和余弦函数的线性组合,从而可以将微分方程转化为常微分方程组。这种转化方法减少了求解微分方程的难度,提高了计算效率。 其次,谱逼近是谱方法的关键步骤之一。它利用正交多项式的特性将函数在区间上的逼近误差控制在极小范围内。这种逼近方法具有高精度和快速收敛的特点,能够有效地求解微分方程。 在实现方面,MATLAB提供了丰富的谱方法函数和工具包,例如fft函数用于进行傅里叶级数展开,polyfit函数用于进行多项式拟合,chebfun工具包用于进行谱逼近等。使用这些函数和工具包,可以方便地编写求解微分方程的程序。 《MATLAB微分方程高效解法: 谱方法原理与实现PDF》对谱方法的原理和实现进行了详细的介绍和讲解。它以通俗易懂的方式阐述了谱方法的数学原理和理论基础,并通过实例和代码演示了如何使用MATLAB实现谱方法求解微分方程。这本教材对于研究微分方程数值解的学者和工程师来说,是一本宝贵的参考资料。 ### 回答3: 谱方法是一种用于求解微分方程的高效方法,它基于谱分析的原理。谱方法将微分方程转化为谱空间中的代数方程,通过将函数展开为一系列基函数的线性组合来逼近解。 在Matlab中,通过谱方法求解微分方程的一般步骤包括以下几个方面。 首先,选择适当的基函数。常用的基函数有Chebyshev多项式、Legendre多项式等。这些基函数具有良好的正交性质,使得展开系数的求解更为简便。 其次,将微分方程转化为谱空间中的代数方程。这一步需要将微分方程中的导数项用基函数展开进行近似,并代入原方程中。最终得到一个关于展开系数的代数方程组。 然后,使用Matlab的线性代数工具求解代数方程组。Matlab提供了丰富的线性代数函数,如矩阵求逆、特征值求解等。通过这些函数,可以高效地求解代数方程组,得到展开系数的解。 最后,利用求解得到的展开系数,通过基函数展开求得微分方程的解。这一步需要使用Matlab的插值函数,如polyval等,通过将展开系数代入基函数的线性组合,即可得到微分方程的近似解。 以上就是Matlab中谱方法求解微分方程的基本原理与实现。通过这种高效的方法,可以有效地求解各种类型的微分方程,并得到精确的数值解。同时,Matlab提供的强大的数值计算工具使得谱方法更易于实现和使用。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值