题解 | #矩阵乘法计算量估算#
矩阵乘法计算量估算
https://www.nowcoder.com/practice/15e41630514445719a942e004edc0a5b
(A(BC))的计算过程:
1.while循环处理最内层括号,取出第一个子串为BC
2.调用递归函数计算BC,计算结果用a替换,变为(Aa),同时将a送入HashMap中,A的value在HashMap中是二维数组{行,列},而a是三维数组{行,列,相乘次数}
3.while循环处理剩余括号,取出子串Aa
4.调用递归函数计算Aa
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Scanner;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Main me = new Main();
Scanner in = new Scanner(System.in);
// 注意 hasNext 和 hasNextLine 的区别
while (in.hasNextLine()) { // 注意 while 处理多个 case
int n = Integer.parseInt(in.nextLine());
//把矩阵放在HashMap中,key为char型的矩阵名称,val为数组{矩阵的行数,矩阵的列数}
HashMap<Character, int[]> nn = new HashMap<>();
for (int i = 0; i < n; i++) {
int temp[] = Arrays.stream(in.nextLine().split(" ")).mapToInt(
c-> Integer.parseInt(c)).toArray();
char key = (char) ('A' + i);
nn.put(key, temp);
}
String s = in.nextLine();
char ress = 'a';//用小写字母来表示子串计算完成后所得的矩阵
//处理字符串中的括号
while (s.contains("(")) {
int f1 = s.lastIndexOf("(");
int e1 = s.indexOf(")", f1);
String snow = s.substring(f1 + 1, e1);
//每次取一个()中的子串进行计算,将子串返回结果做一个三元数组也放在hashmap中
nn.put(ress, me.cishu(snow, nn, new int[] {0, 0, 0}));
String sleft = f1 == 0 ? "" : s.substring(0, f1);
String sright = e1 == s.length() - 1 ? "" : s.substring(e1 + 1);
s = sleft + ress + sright;//更新s,用字串的计算结果(用小写字母表示)替换掉原来的子串
ress += 1;
}
if (s.length() == 1) {
System.out.println(nn.get(s.charAt(0))[2]);
} else {
System.out.println(me.cishu(s, nn, new int[] {0, 0, 0})[2]);
}
}
}
//递归算法计算不带括号的时候相乘次数,返回结果放在一个三元数组-{结果矩阵的行数,结果矩阵的列数,相乘次数},start为初始矩阵,每次用start*子串第一个字母所代表的矩阵,例如子串BC,第一次就是start*B
int[] cishu(String s, HashMap<Character, int[]> ff, int[] start) {
if (s.length() == 0) {
return start;
} else {
char nowc = s.charAt(0);
int[] nows = ff.get(nowc);//当前要相乘的矩阵
s = s.length() == 1 ? "" : s.substring(1);//更新s,作为递归的输入
int ress[];
//当前矩阵可能是以前子串的计算结果例如(A(BC))经过第一次计算后变成(Aa),此时的a是三元组第三个元素是相乘次数,那就要加上这个次数
int nownums = nows.length == 3 ? nows[2] : 0;
if (Arrays.equals(start, new int[] {0, 0, 0})) {//当start矩阵元素都为0时,代表现在是子串的第一个矩阵,那么应该以它本身的行数列数为初始矩阵进入递归
ress = cishu(s, ff, new int[] {nows[0], nows[1], nownums});
} else {//当start矩阵元素不为0时,start是递归返回的结果,那么就计算start*nows
int res = start[2] + start[0] * start[1] * nows[1];
ress = cishu(s, ff, new int[] {start[0], nows[1], nownums + res});
}
return ress;
}
}
}


查看14道真题和解析