[面試攻略] 技術性考題:矩陣相乘

更新於 發佈於 閱讀時間約 12 分鐘

矩陣相乘是一個經典的演算法問題,經常出現在技術面試中,用來評估你對多維陣列的操作和程式設計邏輯的掌握。雖然Python有NumPy這樣的庫可以輕鬆實現矩陣相乘,但面試通常要求你手寫基礎實現,展示對原理的理解。本文將以標準矩陣相乘為例,介紹其基礎概念、Python程式碼、時間與空間複雜度,並提供面試應答技巧。


什麼是矩陣相乘?

矩陣相乘是將兩個矩陣(二維陣列)相乘,得到一個新矩陣。假設你有兩個矩陣:

  • 矩陣 A 是 m x n(m 行 n 列)。
  • 矩陣 B 是 n x p(n 行 p 列)。
  • 結果矩陣 C 是 m x p。

規則C 的每個元素 C[i][j]A 的第 i 行與 B 的第 j 列的點積(對應元素相乘後求和)。

簡單比喻

想像你在製作一份成績表:

  • A 是「學生 x 科目」的分數表。
  • B 是「科目 x 權重」的權重表。
  • C 是「學生 x 加權分數」的結果表。 每個加權分數是學生在各科目的分數乘以對應權重,然後加總。

範例

輸入:
A = [[1, 2],
[3, 4]]
B = [[5, 6],
[7, 8]]

輸出:
C = [[19, 22],
[43, 50]]

計算過程:
C[0][0] = A[0][0] * B[0][0] + A[0][1] * B[1][0] = 1*5 + 2*7 = 19
C[0][1] = A[0][0] * B[0][1] + A[0][1] * B[1][1] = 1*6 + 2*8 = 22
C[1][0] = A[1][0] * B[0][0] + A[1][1] * B[1][0] = 3*5 + 4*7 = 43
C[1][1] = A[1][0] * B[0][1] + A[1][1] * B[1][1] = 3*6 + 4*8 = 50

解法:標準矩陣相乘

矩陣相乘的標準方法使用三層巢狀迴圈,計算每個 C[i][j]

  1. 初始化結果矩陣:
    1. 創建 m x p 的矩陣 C,初始值為 0。
  2. 計算每個元素:
    1. 外層迴圈遍歷 C 的行(i 從 0 到 m-1)。
    2. 中層迴圈遍歷 C 的列(j 從 0 到 p-1)。
    3. 內層迴圈計算點積(k 從 0 到 n-1),累加 A[i][k] * B[k][j]。
  3. 返回結果: 返回填充好的矩陣 C。

簡單比喻

想像你在填一張表格,每個格子(C[i][j])需要把 A 的一行和 B 的一列對應數字相乘,然後加起來。三層迴圈就像你在逐行逐列填表,內層迴圈負責算每個格子的值。


程式碼範例

以下是Python實現,簡單且易於面試手寫:

def matrix_multiply(A, B):
# 獲取矩陣維度
m = len(A) # A 的行數
n = len(A[0]) # A 的列數,B 的行數
p = len(B[0]) # B 的列數

# 初始化結果矩陣 C,大小為 m x p
C = [[0 for _ in range(p)] for _ in range(m)]

# 計算矩陣乘積
for i in range(m): # 遍歷 C 的行
for j in range(p): # 遍歷 C 的列
for k in range(n): # 計算點積
C[i][j] += A[i][k] * B[k][j]

return C

# 測試程式碼
A = [[1, 2],
[3, 4]]
B = [[5, 6],
[7, 8]]

result = matrix_multiply(A, B)
for row in result:
print(row) # 輸出: [19, 22]
# [43, 50]

程式碼解釋

  • 輸入:
    • A 是 m x n 矩陣,B 是 n x p 矩陣。
    • 假設輸入有效(len(A[0]) == len(B))。
  • 初始化:
    • 使用列表推導式創建 m x p 的結果矩陣 C,初始值為 0。
  • 計算:
    • 三層迴圈:
      • i 遍歷 C 的行(0 到 m-1)。
      • j 遍歷 C 的列(0 到 p-1)。
      • k 遍歷 A 的列和 B 的行(0 到 n-1)。
      • 計算 C[i][j] += A[i][k] * B[k][j]。
  • 輸出:
    • 返回結果矩陣 C。
  • Python優勢:無需手動管理記憶體,列表操作直觀。

時間與空間複雜度

  • 時間複雜度:O(m * n * p)
    • 三層迴圈分別迭代 m、p、n 次。
    • 這是標準矩陣相乘的複雜度,進階方法(如Strassen演算法)可降低到 O(n^2.807),但面試中很少要求。
  • 空間複雜度:O(m * p)
    • 用於儲存結果矩陣 C。
    • 如果不計輸出,額外空間為 O(1)(僅用幾個迴圈變數)。

面試應答策略

  • 理解題目:
    • 確認矩陣維度是否有效(A 的列數是否等於 B 的行數)。
    • 詢問是否有特殊情況(空矩陣、單行/列矩陣)。
    • 確認是否需要檢查輸入(例如,矩陣是否為空)。
    • 問清楚是否允許使用庫(如NumPy),通常面試要求手寫。
  • 講解思路:
    • 用簡單比喻(成績表、填表格)讓面試官明白你的思考。
    • 畫圖展示矩陣維度和點積計算(例如,C[0][0] = A[0][0] * B[0][0] + A[0][1] * B[1][0])。
    • 提到三層迴圈的邏輯:i 控制行,j 控制列,k 計算點積。
    • 說明時間複雜度(O(m * n * p))和空間複雜度(O(m * p))。
  • 程式碼實現:
    • 寫乾淨的程式碼,使用有意義的變數名(m, n, p 而不是 x, y, z)。
    • 註釋關鍵步驟,特別是迴圈的作用(行、列、點積)。
    • 處理邊界情況(可加入輸入檢查):
if not A or not B or len(A[0]) != len(B):
return []
  • 進階討論:
    • 如果面試官問到優化,提到:
      • 快取友好:調整迴圈順序(例如,i, k, j)以提高快取命中率。
      • 並行化:將矩陣分塊,交給多執行緒或GPU處理。
      • 進階演算法:Strassen演算法,但強調實務中標準方法更常見(因簡單且易維護)。
    • 討論實際應用:
      • 矩陣相乘用於機器學習(神經網路)、圖形學(變換矩陣)、資料分析。
      • Python中,實務會用NumPy(np.dot)加速計算。
      • 提到Python與C的區別:Python列表操作簡單,但C需要手動分配二維陣列記憶體。
  • 常見追問:
    • 「如果矩陣很大怎麼辦?」回答:分塊處理,減少記憶體使用;使用稀疏矩陣(若適用);考慮分散式計算。
    • 「如何處理稀疏矩陣?」回答:僅儲存非零元素(用字典或壓縮格式如CSR),只計算非零項的乘積。
    • 「如何處理浮點數精度?」回答:使用高精度數學庫(如 decimal),或在最後四捨五入。
    • 「Python與C++實現的區別?」回答:Python無需手動記憶體管理,列表推導式簡化初始化;C++需用指標或 std::vector,小心記憶體洩漏。
  • 模擬面試準備:
    • 在LeetCode練習矩陣相關題目(#73 Set Matrix Zeroes, #54 Spiral Matrix)。
    • 手寫程式碼,模擬白板環境,練習邊寫邊講解。
    • 測試邊界情況(空矩陣、1x1矩陣、不相容維度)。
    • 熟悉Python的列表操作,確保不誤用賦值或索引。

進階範例:加入輸入檢查

以下是一個更穩健的實現,包含輸入驗證,展示面試中如何處理邊界情況:

def matrix_multiply(A, B):
# 檢查輸入
if not A or not B or not A[0] or not B[0]:
return []
if len(A[0]) != len(B):
return []

# 獲取矩陣維度
m = len(A) # A 的行數
n = len(A[0]) # A 的列數,B 的行數
p = len(B[0]) # B 的列數

# 初始化結果矩陣
C = [[0 for _ in range(p)] for _ in range(m)]

# 計算矩陣乘積
for i in range(m):
for j in range(p):
for k in range(n):
C[i][j] += A[i][k] * B[k][j]

return C

# 測試
A = [[1, 2],
[3, 4]]
B = [[5, 6],
[7, 8]]
result = matrix_multiply(A, B)
for row in result:
print(row) # 輸出: [19, 22]
# [43, 50]

# 測試邊界
A_empty = []
B_invalid = [[1], [2]]
print(matrix_multiply(A_empty, B)) # 輸出: []
print(matrix_multiply(A, B_invalid)) # 輸出: []

說明

  • 輸入檢查:
    • 檢查空矩陣(A 或 B 為空,或包含空行)。
    • 檢查維度是否相容(len(A[0]) != len(B))。
  • 穩健性:返回空列表表示無效輸入,符合面試對邊界處理的要求。
  • 清晰性:程式碼結構分明,註釋說明每個步驟。

結語

矩陣相乘是面試中的基礎題目,掌握標準三層迴圈實現能展示你對陣列操作和演算法的理解。使用Python時,重點在於寫出乾淨的程式碼並處理邊界情況。練習時,專注於講解邏輯(用成績表比喻)、分析複雜度,並準備回答優化問題。模擬面試時,練習邊寫邊講解,確保程式碼無誤且表達清晰。其他矩陣題目(如旋轉矩陣、稀疏矩陣)也可能出現,建議在LeetCode上多練幾題。祝大家面試順利!



留言
avatar-img
留言分享你的想法!
avatar-img
追極光的北極熊|軟體工程師的小天地
9會員
145內容數
歡迎來到我的部落格!這裡記錄了軟體工程師的日常生活點滴,並分享程式設計與演算法的實用教學。無論你是初學者還是有經驗的開發者,都能在這裡找到深入淺出的技術解析與實戰技巧。此外,我也會分享工作中的心路歷程與學習心得,讓你不僅學到技術,更能瞭解軟體開發的實際應用與挑戰。希望透過這個平台,能與你共同成長,激發對技術的熱情!
你可能也想看
Thumbnail
TOMICA第一波推出吉伊卡哇聯名小車車的時候馬上就被搶購一空,一直很扼腕當時沒有趕緊入手。前陣子閒來無事逛蝦皮,突然發現幾家商場都又開始重新上架,價格也都回到正常水準,估計是官方又再補了一批貨,想都沒想就立刻下單! 同文也跟大家分享近期蝦皮購物紀錄、好用推薦、蝦皮分潤計畫的聯盟行銷!
Thumbnail
TOMICA第一波推出吉伊卡哇聯名小車車的時候馬上就被搶購一空,一直很扼腕當時沒有趕緊入手。前陣子閒來無事逛蝦皮,突然發現幾家商場都又開始重新上架,價格也都回到正常水準,估計是官方又再補了一批貨,想都沒想就立刻下單! 同文也跟大家分享近期蝦皮購物紀錄、好用推薦、蝦皮分潤計畫的聯盟行銷!
Thumbnail
每年4月、5月都是最多稅要繳的月份,當然大部份的人都是有機會繳到「綜合所得稅」,只是相當相當多人還不知道,原來繳給政府的稅!可以透過一些有活動的銀行信用卡或電子支付來繳,從繳費中賺一點點小確幸!就是賺個1%~2%大家也是很開心的,因為你們把沒回饋變成有回饋,就是用卡的最高境界 所得稅線上申報
Thumbnail
每年4月、5月都是最多稅要繳的月份,當然大部份的人都是有機會繳到「綜合所得稅」,只是相當相當多人還不知道,原來繳給政府的稅!可以透過一些有活動的銀行信用卡或電子支付來繳,從繳費中賺一點點小確幸!就是賺個1%~2%大家也是很開心的,因為你們把沒回饋變成有回饋,就是用卡的最高境界 所得稅線上申報
Thumbnail
題目敘述 Combination Sum II_Leetcode #40 給定一個整數陣列candidates 和 目標值target。 每個陣列元素只能選擇一次,請問有多少種組合方法,可以使得組合數總和 = target? 請把滿足組合數總和 = target的組合方法以陣列的形式返回答案
Thumbnail
題目敘述 Combination Sum II_Leetcode #40 給定一個整數陣列candidates 和 目標值target。 每個陣列元素只能選擇一次,請問有多少種組合方法,可以使得組合數總和 = target? 請把滿足組合數總和 = target的組合方法以陣列的形式返回答案
Thumbnail
Leetcode 精選75題 題目與題解 熱門考點 目錄 (持續更新中) 建議從左側目錄 或者 按Ctrl+F輸入關鍵字進行搜尋
Thumbnail
Leetcode 精選75題 題目與題解 熱門考點 目錄 (持續更新中) 建議從左側目錄 或者 按Ctrl+F輸入關鍵字進行搜尋
Thumbnail
分享在網路上看到的陣列題目。通常 for...of 的 value 是陣列中的每個值,那如果我們在迭代中對陣列操作會發生什麼事? 題目來源:https://x.com/_jayphelps/status/1774640511158022335?s=20
Thumbnail
分享在網路上看到的陣列題目。通常 for...of 的 value 是陣列中的每個值,那如果我們在迭代中對陣列操作會發生什麼事? 題目來源:https://x.com/_jayphelps/status/1774640511158022335?s=20
Thumbnail
這篇文章,會帶著大家複習以前學過的遞回框架, 並且鏈結串列的概念與應用為核心, 貫穿一些相關聯的題目,透過框架複現來幫助讀者理解這個演算法框架。 遞回框架 尋找共通模式(common pattern),對應到演算法的General case 確立初始條件(initial conditio
Thumbnail
這篇文章,會帶著大家複習以前學過的遞回框架, 並且鏈結串列的概念與應用為核心, 貫穿一些相關聯的題目,透過框架複現來幫助讀者理解這個演算法框架。 遞回框架 尋找共通模式(common pattern),對應到演算法的General case 確立初始條件(initial conditio
Thumbnail
題目會給定一個陣列nums和一個目標值goal。計算子陣列總和=goal的數目有多少。演算法包含前綴和和字典的技巧,時間複雜度為O(n),空間複雜度為O(n)。
Thumbnail
題目會給定一個陣列nums和一個目標值goal。計算子陣列總和=goal的數目有多少。演算法包含前綴和和字典的技巧,時間複雜度為O(n),空間複雜度為O(n)。
Thumbnail
題目敘述 題目會給定我們一個輸入陣列nums,要求我們掃描美個陣列元素nums[i],計算除了nums[i]以外的陣列元素連乘積。 題目的原文敘述 測試範例 Example 1: Input: nums = [1,2,3,4] Output: [24,12,8,6] nums[0] 以
Thumbnail
題目敘述 題目會給定我們一個輸入陣列nums,要求我們掃描美個陣列元素nums[i],計算除了nums[i]以外的陣列元素連乘積。 題目的原文敘述 測試範例 Example 1: Input: nums = [1,2,3,4] Output: [24,12,8,6] nums[0] 以
Thumbnail
題目敘述 題目會給定一個輸入字串s和一套編碼規則,要求我們針對字串s進行解碼,並且以字串的形式返回答案。 編碼規則: 數字[字串] -> []內的字串以對應倍數做展開,而且允許巢狀編碼。 例如: 3[a] 解碼完就是 aaa 2[bc] 解碼完就是 bcbc 2[a2[b]] = 2
Thumbnail
題目敘述 題目會給定一個輸入字串s和一套編碼規則,要求我們針對字串s進行解碼,並且以字串的形式返回答案。 編碼規則: 數字[字串] -> []內的字串以對應倍數做展開,而且允許巢狀編碼。 例如: 3[a] 解碼完就是 aaa 2[bc] 解碼完就是 bcbc 2[a2[b]] = 2
Thumbnail
題目敘述 題目會給定我們兩個整數陣列作為輸入nums1, nums2,要求我們找出兩個陣列的差異值。 找出在nums1但是不在nums2的元素,以陣列的形式放在answer[0]輸出。 找出在nums2但是不在nums1的元素,以陣列的形式放在answer[1]輸出。 題目的原文敘述
Thumbnail
題目敘述 題目會給定我們兩個整數陣列作為輸入nums1, nums2,要求我們找出兩個陣列的差異值。 找出在nums1但是不在nums2的元素,以陣列的形式放在answer[0]輸出。 找出在nums2但是不在nums1的元素,以陣列的形式放在answer[1]輸出。 題目的原文敘述
Thumbnail
題目敘述 題目給定我們一個輸入陣列nums 要求我們以正、負交叉排列的方式重組陣列,並且必須保持原本的相對順序。 並且以陣列的形式輸出返回答案。 例[5, 1, -2, -3] 重排後為 [5, -2, 1, -3] 題目的原文敘述 測試範例 Example 1: Input:
Thumbnail
題目敘述 題目給定我們一個輸入陣列nums 要求我們以正、負交叉排列的方式重組陣列,並且必須保持原本的相對順序。 並且以陣列的形式輸出返回答案。 例[5, 1, -2, -3] 重排後為 [5, -2, 1, -3] 題目的原文敘述 測試範例 Example 1: Input:
Thumbnail
究竟誰是 i、誰又是 j?矩陣問題務必趁腦子清楚時才解 XDD
Thumbnail
究竟誰是 i、誰又是 j?矩陣問題務必趁腦子清楚時才解 XDD
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News