校招算法笔面试 | 华为机试-矩阵乘法计算量估算

题目## 题目

题目链接

解题思路

  1. 题目要求:

    • 计算矩阵乘法的运算次数
    • 根据给定的计算顺序(括号表达式)来确定运算顺序
    • 矩阵个数n: 1 ≤ n ≤ 15 1 \leq n \leq 15 1n15
    • 矩阵行列数: 1 ≤ r o w , c o l ≤ 100 1 \leq row, col \leq 100 1row,col100
  2. 关键点:

    • 使用栈来存储待计算的矩阵信息
    • 遇到右括号时,处理最近的两个矩阵相乘
    • 计算量 = 第一个矩阵的行数 × 第一个矩阵的列数 × 第二个矩阵的列数

代码

while True:
    try:
        n = int(input())
        arr = []
        order = []
        res = 0
        # 读取矩阵维度信息
        for i in range(n):
            arr.append(list(map(int, input().split())))
        
        # 读取计算顺序
        f = input()
        for i in f:
            if i.isalpha():
                # 将字母转换为对应矩阵的维度信息
                order.append(arr[ord(i)-65])
            elif i == ')' and len(order) >= 2:
                # 遇到右括号,处理最近的两个矩阵
                b = order.pop()
                a = order.pop()
                # 计算乘法运算次数并累加
                res += a[0] * a[1] * b[1]
                # 将结果矩阵压入栈中
                order.append([a[0], b[1]])
        print(res)
    except:
        break
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (sc.hasNext()) {
            int n = sc.nextInt();
            int[][] arr = new int[n][2];
            List<int[]> order = new ArrayList<>();
            int res = 0;
            
            // 读取矩阵维度信息
            for (int i = 0; i < n; i++) {
                arr[i][0] = sc.nextInt();
                arr[i][1] = sc.nextInt();
            }
            
            // 读取计算顺序
            String f = sc.next();
            for (char c : f.toCharArray()) {
                if (Character.isLetter(c)) {
                    // 将字母转换为对应矩阵的维度信息
                    order.add(arr[c - 'A']);
                } else if (c == ')' && order.size() >= 2) {
                    // 遇到右括号,处理最近的两个矩阵
                    int[] b = order.remove(order.size() - 1);
                    int[] a = order.remove(order.size() - 1);
                    // 计算乘法运算次数并累加
                    res += a[0] * a[1] * b[1];
                    // 将结果矩阵压入栈中
                    order.add(new int[]{a[0], b[1]});
                }
            }
            System.out.println(res);
        }
    }
}
#include <iostream>
#include <vector>
using namespace std;

int main() {
    int n;
    while (cin >> n) {
        vector<vector<int>> arr(n, vector<int>(2));
        vector<vector<int>> order;
        int res = 0;
        
        // 读取矩阵维度信息
        for (int i = 0; i < n; i++) {
            cin >> arr[i][0] >> arr[i][1];
        }
        
        // 读取计算顺序
        string f;
        cin >> f;
        for (char c : f) {
            if (isalpha(c)) {
                // 将字母转换为对应矩阵的维度信息
                order.push_back(arr[c - 'A']);
            } else if (c == ')' && order.size() >= 2) {
                // 遇到右括号,处理最近的两个矩阵
                vector<int> b = order.back();
                order.pop_back();
                vector<int> a = order.back();
                order.pop_back();
                // 计算乘法运算次数并累加
                res += a[0] * a[1] * b[1];
                // 将结果矩阵压入栈中
                order.push_back({a[0], b[1]});
            }
        }
        cout << res << endl;
    }
    return 0;
}

算法分析

  1. 时间复杂度: O ( n ) \mathcal{O}(n) O(n)

    • n为表达式长度
    • 每个字符只需处理一次
  2. 空间复杂度: O ( n ) \mathcal{O}(n) O(n)

    • 需要一个栈来存储矩阵信息

题目链接

解题思路

  1. 首先读取输入:

    • 第一个矩阵的行数 x x x
    • 第一个矩阵的列数和第二个矩阵的行数 y y y
    • 第二个矩阵的列数 z z z
    • 然后分别读取两个矩阵的元素
  2. 进行矩阵乘法计算:

    • 结果矩阵的大小为 x × z x \times z x×z
    • 对于结果矩阵中的每个元素 C [ i ] [ j ] C[i][j] C[i][j],计算公式为:
      C [ i ] [ j ] = ∑ k = 0 y − 1 A [ i ] [ k ] × B [ k ] [ j ] C[i][j] = \sum_{k=0}^{y-1} A[i][k] \times B[k][j] C[i][j]=k=0y1A[i][k]×B[k][j]
  3. 输出结果矩阵


代码

while True:
    try:
        # 读取矩阵维度
        x = int(input())
        y = int(input())
        z = int(input())
        
        # 读取第一个矩阵
        matrix1 = []
        for _ in range(x):
            row = list(map(int, input().split()))
            matrix1.append(row)
            
        # 读取第二个矩阵
        matrix2 = []
        for _ in range(y):
            row = list(map(int, input().split()))
            matrix2.append(row)
            
        # 计算矩阵乘法
        result = [[0] * z for _ in range(x)]
        for i in range(x):
            for j in range(z):
                for k in range(y):
                    result[i][j] += matrix1[i][k] * matrix2[k][j]
        
        # 输出结果
        for row in result:
            print(' '.join(map(str, row)))
            
    except EOFError:
        break
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (sc.hasNext()) {
            // 读取矩阵维度
            int x = sc.nextInt();
            int y = sc.nextInt();
            int z = sc.nextInt();
            
            // 读取第一个矩阵
            int[][] matrix1 = new int[x][y];
            for (int i = 0; i < x; i++) {
                for (int j = 0; j < y; j++) {
                    matrix1[i][j] = sc.nextInt();
                }
            }
            
            // 读取第二个矩阵
            int[][] matrix2 = new int[y][z];
            for (int i = 0; i < y; i++) {
                for (int j = 0; j < z; j++) {
                    matrix2[i][j] = sc.nextInt();
                }
            }
            
            // 计算矩阵乘法
            int[][] result = new int[x][z];
            for (int i = 0; i < x; i++) {
                for (int j = 0; j < z; j++) {
                    for (int k = 0; k < y; k++) {
                        result[i][j] += matrix1[i][k] * matrix2[k][j];
                    }
                }
            }
            
            // 输出结果
            for (int i = 0; i < x; i++) {
                for (int j = 0; j < z; j++) {
                    System.out.print(result[i][j]);
                    if (j < z - 1) {
                        System.out.print(" ");
                    }
                }
                System.out.println();
            }
        }
    }
}
#include <iostream>
#include <vector>
using namespace std;

int main() {
    int x, y, z;
    while (cin >> x >> y >> z) {
        // 读取第一个矩阵
        vector<vector<int>> matrix1(x, vector<int>(y));
        for (int i = 0; i < x; i++) {
            for (int j = 0; j < y; j++) {
                cin >> matrix1[i][j];
            }
        }
        
        // 读取第二个矩阵
        vector<vector<int>> matrix2(y, vector<int>(z));
        for (int i = 0; i < y; i++) {
            for (int j = 0; j < z; j++) {
                cin >> matrix2[i][j];
            }
        }
        
        // 计算矩阵乘法
        vector<vector<int>> result(x, vector<int>(z, 0));
        for (int i = 0; i < x; i++) {
            for (int j = 0; j < z; j++) {
                for (int k = 0; k < y; k++) {
                    result[i][j] += matrix1[i][k] * matrix2[k][j];
                }
            }
        }
        
        // 输出结果
        for (int i = 0; i < x; i++) {
            for (int j = 0; j < z; j++) {
                cout << result[i][j];
                if (j < z - 1) cout << " ";
            }
            cout << endl;
        }
    }
    return 0;
}

算法及复杂度

  • 算法:矩阵乘法的基本实现
  • 时间复杂度: O ( x × y × z ) \mathcal{O}(x \times y \times z) O(x×y×z) - 三重循环实现矩阵乘法
  • 空间复杂度: O ( x × z ) \mathcal{O}(x \times z) O(x×z) - 存储结果矩阵
108题中有部分题目重合,因此么有收录在压缩文件中。 华为 ├─001 字符串最后一个单词长度 │ └─Source ├─002 计算字符个数 │ └─Source ├─003 明明的随数 │ └─Source ├─004 字符串分隔 │ └─Source ├─005 进制转换 │ └─Source ├─006 质数因子 │ └─Source ├─007 取近似值 │ └─Source ├─008 合并表记录 │ └─Source ├─009 提取不重复的整数 │ └─Source ├─010 字符个数统计 │ └─Source ├─011 数字颠倒 │ └─Source ├─012 字符串反转 │ └─Source ├─013 句子逆序 │ └─Source ├─014 字典序排序 │ └─Source ├─015 求int型正整数在内存中存储是1的个数 │ └─Source ├─016 购物单 │ ├─Debug │ ├─Source │ │ └─Debug │ ├─Source - 时间优先 │ │ └─Debug │ └─Source - 空间优先 │ ├─Debug │ └─Release ├─017 坐标移动 ├─018 识别IP地址分类统计 │ └─Source │ └─Debug ├─019 错误记录 ├─020 密码验证合格程序 ├─021 密码破解 ├─023 删除字符串中出现次数最少字符 │ └─Source │ └─Debug ├─024 合唱队 │ └─Source │ ├─Debug │ └─Release ├─025 数据分类处理 │ └─Source │ └─Debug ├─026 查找兄弟单词 │ └─Source │ └─Debug ├─027 素数伴侣 │ └─Source │ └─Debug ├─028 字符串合并处理 │ └─Source │ └─Debug ├─030 密码截取(查找最长回文字符串) ├─031 蛇形矩阵 │ └─Source │ └─Debug ├─033 判断IP是否属于同一子网 │ └─Source │ └─Debug ├─034 称砝码 │ └─Source │ └─Debug ├─035 学英语 │ └─Source │ └─Debug ├─036 迷宫问题 │ └─Source │ └─Debug ├─037 数独问题 │ └─Debug ├─038 名字漂亮度 │ └─Source │ └─Debug ├─039 字符串截取 │ └─Source │ └─Debug ├─040 单链表删除数据 │ └─Source │ └─Debug ├─041 多线程 │ └─Source │ ├─Backup │ ├─Debug │ │ └─041.tlog │ └─Release │ └─041.tlog ├─042 表达式计算 │ └─Source │ └─Debug ├─043 计算字符串距离 │ └─Source │ └─Debug ├─044 杨辉三角形变形 ├─046 挑7 ├─047 完全数 │ └─Debug ├─048 高精度加法 ├─049 输出n个数中最小的k个 │ └─Debug ├─050 找出字符串只出现一次的字符 │ └─Debug ├─051 组成一个偶数最接近的2个质数 │ └─Debug ├─052 M个苹果放入N个盘子 ├─053 查找整数二进制中1的个数 ├─054 DNA子串 ├─055 MP3光标位置 │ └─Source │ └─Debug ├─056 查找2个字符串最大相同子串 │ └─Debug ├─057 配置文件恢复 │ └─Source │ └─Debug ├─058 24点计算 │ └─Debug ├─059 成绩排序 ├─060 矩阵相乘 ├─061 矩阵乘法次数计算 ├─062 字符串通配符 │ └─Debug ├─066 命令行解析 │ └─Source │ └─Debug ├─067 最大相同子串长度 │ └─Debug ├─068 火车编号进站 │ └─Debug ├─072 数组合并 ├─074 埃及分数 │ └─Source │ └─Debug ├─076 密码截取 │ └─Source ├─077 求最大连续bit数 ├─078 密码强度 ├─079 扑克牌大小 │ └─Source │ └─Debug ├─081 合法IP ├─082 棋盘格子走法 ├─083 在字符串中找出连续最长数字串 ├─084 int数组分组,两组和相等 │ └─Source │ └─Debug ├─086 人民币转换 │ └─Source │ └─Debug ├─087 表示数字 ├─090 自动售货系统 │ └─Source │ └─Debug └─091 24点输出 └─Debug
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值