为运算表达式设计优先级的思路探讨与源码
为运算表达式设计优先级的题目如下图,该题属于分治类和动态规划类型的题目,主要考察对于分治方法的使用和动态规划思路的理解。本文的题目作者想到2种方法,分别是分治方法和动态规划方法,其中动态规划方法使用Java进行编写,而分治方法使用Python进行编写,当然这可能不是最优的解法,还希望各位大佬给出更快的算法。
本人认为该题目可以使用动态规划方法的思路进行解决,首先把字符串表达式里面的数字提取出来,整理成为数组。再把数字全部替换并只要保留运算符,并且计算数组的长度,初始化一个动态规划的存储矩阵。开始遍历数字数组,把数字拿出来赋值到动态规划矩阵的元素,继续遍历并把运算符的结果拿出并对子数组的所有结果进行遍历,如果是加法就把数字求和、如果是减法就将数字相减、否则就把数字相乘。以此循环遍历并得到最终结果,返回矩阵的右上角的值就是最终的计算结果。那么按照这个思路我们的Java代码如下:
#喷火龙与水箭龟
class Solution {
public List<Integer> diffWaysToCompute(String expression) {
String[] numArr = expression.split("[+\\-*]");
String flagStr = expression.replaceAll("[0-9]", "");
int numLen = numArr.length;
List<Integer>[][] matrix = new List[numLen][numLen];
for (int ir=numLen-1;ir>= 0;ir--) {
matrix[ir][ir] = Collections.singletonList(Integer.parseInt(numArr[ir]));
for (int jr=ir+1;jr<numLen;jr++) {
matrix[ir][jr] = new ArrayList<>();
for (int kr=ir;kr<jr;kr++) {
char flag = flagStr.charAt(kr);
for (int ur:matrix[ir][kr]) {
for (int vr:matrix[kr+1][jr]) {
if(flag==('+')){
matrix[ir][jr].add(ur+vr);
}else if(flag==('-')){
matrix[ir][jr].add(ur-vr);
}else{
matrix[ir][jr].add(ur*vr);
}
}
}
}
}
}
return matrix[0][numLen-1];
}
}
显然,我们看到动态规划方法效果比较一般,同时还可以使用分治方法解决。首先判断字符串是否为数字,如果是就直接返回结果。初始化一个结果列表,对输入的字符串进行遍历,如果元素是属于加法或者减法或者乘法的运算符,那么就把字符串左边和右边进行分割,得到的子字符串分别调用当前函数,得到的结果进行返回,对左边和右边的结果进行遍历,如果元素值是加法,就把当前的两个数字值相加并加入到结果列表;如果元素值是减法,就把当前的两个数字值相减并加入到结果列表;如果都不是,就把当前的两个数字相乘并加入到结果列表。按照这个逻辑遍历,最终返回列表的结果。所以按照这个思路就可以解决,下面是Python代码:
#喷火龙与水箭龟
class Solution:
def diffWaysToCompute(self, input: str) -> List[int]:
if(input.isdigit()):
rs = int(input)
return [rs]
resFinal = []
for jr,kr in enumerate(input):
if(kr in ['+', '-', '*']):
a = self.diffWaysToCompute(input[:jr])
b = self.diffWaysToCompute(input[jr+1:])
for jm in a:
for km in b:
if(kr=='+'):
resFinal.append(jm+km)
elif(kr=='-'):
resFinal.append(jm-km)
else:
resFinal.append(jm*km)
return resFinal
从结果来说Java版本的动态规划的效率比较差,而Python版本的分治方法的速度还可以,但应该是有更多的方法可以进一步提速的,希望朋友们能够多多指教,非常感谢。