题解 | #矩阵乘法计算量估算#
矩阵乘法计算量估算
https://www.nowcoder.com/practice/15e41630514445719a942e004edc0a5b
import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 注意 hasNext 和 hasNextLine 的区别
int num = Integer.parseInt(in.nextLine());
int[][] matrixs = new int[num][2];
for (int i = 0; i < num; i++) {
String[] matrixItem = in.nextLine().split(" ");
//合法性检验
if (i != 0 && matrixs[i - 1][1] != Integer.parseInt(matrixItem[0])) {
System.out.println("矩阵输入不合法");
in.close();
} else {
matrixs[i][0] = Integer.parseInt(matrixItem[0]);
matrixs[i][1] = Integer.parseInt(matrixItem[1]);
}
}
String rule = in.nextLine();
char[] ruleArr = rule.toCharArray();
in.close();
//使用栈结构,左括号则入栈;字母则取行列入栈,连续字母直接运算后只留下一个;右括号则出栈并去括号
Stack<String> stk = new Stack<String>();
int matrixIndex = 0;
int counts = 0;
for (char c : ruleArr) {
if (c == '(') { //左括号入栈
stk.push(c + "");
} else if ( c >= 'A' && c <= 'Z') { //矩阵符号
int nowRow = matrixs[matrixIndex][0];
int nowColumn = matrixs[matrixIndex][1];
if ( !stk.peek().equals("(") && !stk.peek().equals(")") ) {
//栈顶(前一个符号)也是字母,则可以立即进行运算得到矩阵入栈
int preColumn = Integer.parseInt(stk.pop());
int preRow = Integer.parseInt(stk.pop());
int count = preRow * preColumn * nowColumn;
stk.push(preRow + "");
stk.push(nowColumn + "");
counts += count;
} else { //前一个不是字母则将矩阵行列入栈
stk.push(nowRow + "");
stk.push(nowColumn + "");
}
matrixIndex++;
} else if ( c == ')') { //由于前面的运算,括号里最多只有一个矩阵的行列
if ( stk.peek() == "(") { //括号里面为空,直接都出栈
stk.pop();
} else if ( !stk.peek().equals("(") && !stk.peek().equals(")") ){
int nowColumn = Integer.parseInt(stk.pop());
int nowRow = Integer.parseInt(stk.pop());
stk.pop(); //弹出左括号
if ( stk.size() != 0 && !stk.peek().equals("(") && !stk.peek().equals(")") ){
//去掉括号后如果又是矩阵,同样需要运算,但所幸,嵌套到这里就不用往更深了
int preColumn = Integer.parseInt(stk.pop());
int preRow = Integer.parseInt(stk.pop());
int count = preRow * preColumn * nowColumn;
stk.push(preRow + "");
stk.push(nowColumn + "");
counts += count;
} else {
stk.push(nowRow + "");
stk.push(nowColumn + "");
}
}
}
}
System.out.println(counts);
}
}
看了其他大神的题解,都比较约定俗成的认为括号内只有两个连续的矩阵,即不会出现()、(ABC)、(A)这种情况,构思许久,写下这个,同样是以栈的方式实现,而且只需遍历一次就可以,就是逻辑判断啥的比较多,代码附上,还请大神可以优化优化,一起学习!
下面我主要讲讲字符串遍历思路,代码中也有相对应的注释。
- 左括号直接入栈;
- 如果是矩阵,判断之前是否也有矩阵,有则两个直接计算乘法次数,以及变成新矩阵入栈,如[3, 2] * [2, 5]转成[3, 5];没有则直接入栈行和列;
- 如果是右括号,由于之前有运算,那么栈顶要么是矩阵,要么是左括号(考虑了字符串中输入了“()”的情况),总之思路是要消去两边括号,就像我们学习四则运算一样,括号内计算好了就可以去括号。例如(B),就popB,pop(,然后在压入B
- 这是我运行了用例之后有部分不通过发现的需要增加的判断,如果我们去了括号之后,发现有连续的矩阵在一起,比如A(B),去掉括号就是AB,还是需要运算后再继续遍历字符。具体就是在第3条压入B之前,判断栈顶是否是矩阵,是就采用第2条同样操作去处理连续字符串。
举个比较综合的例子,其栈的情况及操作分析:
(A((BCD)E)()(FG))
1.入栈,A和B入栈时都判断了前面没有矩阵相连,直接入栈:(, Ar, Ac, (, (, Br, Bc
2.矩阵C进来后判断到前面有B,运算:(, Ar, Ac, (, (, Br, Cc
3.矩阵D进来后判断到前面有矩阵,运算:(, Ar, Ac, (, (, Br, Dc
4.遇到')',前面是刚刚计算的ABC的矩阵,因此出出,消掉括号'(',但再左边还是括号而不是矩阵,所以不用运算先:(, Ar, Ac, (, Br, Dc
5.矩阵E进来,左边是矩阵,运算:(, Ar, Ac, (, Br, Ec
6.')'进来,去括号,发现前面连着矩阵A,所以要运算:(, Ar, Ec
7.'('直接入栈:(, Ar, Ec, (
8.')'进来,去括号:(, Ar, Ec
9.'('直接入栈:(, Ar, Ec, (
10.矩阵F进来,前面是'('而不是矩阵,所以行列入栈:(, Ar, Ec, (, Fr, Fc
11.矩阵G进来,前面有F所以运算:(, Ar, Ec, (, Fr, Gc
12.')'进来,去括号而且运算:(, Ar, Gc
13.')'进来,去括号:Ar, Gc
至此,字符串遍历完成即算法完成,栈中剩下的是结果矩阵的行和列数,乘法次数在运算中累加就可以。

SHEIN希音公司福利 276人发布