【華為機試】240. 搜索二維矩陣 II

文章目錄

  • 240. 搜索二維矩陣 II
    • 描述
    • 示例 1
    • 示例 2
    • 提示
    • 解題思路
      • 核心分析
      • 問題轉化
      • 算法實現
        • 方法1:右上角開始搜索(推薦)
        • 方法2:逐行二分查找
        • 方法3:分治法
        • 方法4:左下角開始搜索
    • 復雜度分析
    • 核心要點
    • 數學證明
      • 右上角搜索法正確性證明
      • 時間復雜度分析
    • 執行流程圖
    • 搜索路徑示意圖
    • 實際應用
    • 算法優化技巧
      • 1. 預處理優化
      • 2. 邊界優化
      • 3. 緩存優化
    • 擴展思考
    • 測試用例設計
    • 性能對比
    • 總結
    • 完整題解代碼

240. 搜索二維矩陣 II

描述

編寫一個高效的算法來搜索 m x n 矩陣 matrix 中的一個目標值 target 。該矩陣具有以下特性:

  • 每行的元素從左到右升序排列。
  • 每列的元素從上到下升序排列。

示例 1

在這里插入圖片描述

輸入:matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 5
輸出:true

示例 2

在這里插入圖片描述

輸入:matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 20
輸出:false

提示

  • m == matrix.length
  • n == matrix[i].length
  • 1 <= n, m <= 300
  • -10^9 <= matrix[i][j] <= 10^9
  • 每行的所有元素從左到右升序排列
  • 每列的所有元素從上到下升序排列
  • -10^9 <= target <= 10^9

解題思路

核心分析

這道題是一個典型的有序矩陣搜索問題。關鍵在于充分利用矩陣的雙向有序性

  • 行有序:每行從左到右遞增
  • 列有序:每列從上到下遞增

這種特殊的有序性為我們提供了多種高效的搜索策略。

問題轉化

由于矩陣的特殊有序性,我們可以從不同角度思考:

  1. 角點策略:選擇具有特殊性質的起始點
  2. 分治策略:遞歸分解搜索空間
  3. 線性策略:逐行或逐列進行優化搜索

算法實現

方法1:右上角開始搜索(推薦)

核心思想:利用右上角元素的獨特性質進行搜索

算法原理

  • 右上角元素是當前行的最大值
  • 右上角元素是當前列的最小值
  • 這種性質確保了每次比較都能排除一行或一列

狀態定義

  • row:當前行索引
  • col:當前列索引
  • 初始位置:(0, n-1) 右上角

轉移策略

if matrix[row][col] == target:return true
elif matrix[row][col] > target:col--  // 向左移動,排除當前列
else:row++  // 向下移動,排除當前行
func searchMatrix(matrix [][]int, target int) bool {if len(matrix) == 0 || len(matrix[0]) == 0 {return false}row, col := 0, len(matrix[0])-1for row < len(matrix) && col >= 0 {if matrix[row][col] == target {return true} else if matrix[row][col] > target {col-- // 向左移動} else {row++ // 向下移動}}return false
}

時間復雜度:O(m + n),最多遍歷m+n個元素
空間復雜度:O(1)

方法2:逐行二分查找

核心思想:在每行中使用二分查找

算法步驟

  1. 遍歷矩陣的每一行
  2. 在每行中進行二分查找
  3. 找到目標值即返回true
func searchMatrixBinarySearch(matrix [][]int, target int) bool {if len(matrix) == 0 || len(matrix[0]) == 0 {return false}for _, row := range matrix {if binarySearch(row, target) {return true}}return false
}func binarySearch(arr []int, target int) bool {left, right := 0, len(arr)-1for left <= right {mid := left + (right-left)/2if arr[mid] == target {return true} else if arr[mid] < target {left = mid + 1} else {right = mid - 1}}return false
}

時間復雜度:O(m × log n)
空間復雜度:O(1)

方法3:分治法

核心思想:遞歸分解搜索空間

算法步驟

  1. 選擇矩陣中間元素作為比較基準
  2. 根據比較結果遞歸搜索對應區域
  3. 利用有序性剪枝無效區域
func searchMatrixDivideConquer(matrix [][]int, target int) bool {if len(matrix) == 0 || len(matrix[0]) == 0 {return false}return divideConquer(matrix, target, 0, 0, len(matrix)-1, len(matrix[0])-1)
}func divideConquer(matrix [][]int, target, row1, col1, row2, col2 int) bool {if row1 > row2 || col1 > col2 {return false}if row1 == row2 && col1 == col2 {return matrix[row1][col1] == target}midRow := (row1 + row2) / 2midCol := (col1 + col2) / 2if matrix[midRow][midCol] == target {return true} else if matrix[midRow][midCol] > target {return divideConquer(matrix, target, row1, col1, midRow-1, col2) ||divideConquer(matrix, target, midRow, col1, row2, midCol-1)} else {return divideConquer(matrix, target, midRow+1, col1, row2, col2) ||divideConquer(matrix, target, row1, midCol+1, midRow, col2)}
}

時間復雜度:O(n^log?3) ≈ O(n^1.585)
空間復雜度:O(log n)

方法4:左下角開始搜索

核心思想:從左下角開始,利用其特殊性質

算法原理

  • 左下角元素是當前行的最小值
  • 左下角元素是當前列的最大值
func searchMatrixBottomLeft(matrix [][]int, target int) bool {if len(matrix) == 0 || len(matrix[0]) == 0 {return false}row, col := len(matrix)-1, 0for row >= 0 && col < len(matrix[0]) {if matrix[row][col] == target {return true} else if matrix[row][col] > target {row-- // 向上移動} else {col++ // 向右移動}}return false
}

時間復雜度:O(m + n)
空間復雜度:O(1)

復雜度分析

方法時間復雜度空間復雜度優缺點
右上角搜索O(m + n)O(1)最優解,思路簡潔
左下角搜索O(m + n)O(1)與右上角搜索等價
逐行二分查找O(m × log n)O(1)思路直觀,但效率較低
分治法O(n^1.585)O(log n)理論較優,實際常數項較大
暴力搜索O(m × n)O(1)最簡單,未利用有序性

核心要點

  1. 角點選擇:右上角和左下角具有特殊的大小關系
  2. 有序性利用:充分利用行列雙向有序的特性
  3. 搜索方向:每次比較都能確定唯一的搜索方向
  4. 剪枝優化:每步操作都能排除一行或一列

數學證明

右上角搜索法正確性證明

定理:從右上角開始的搜索策略能夠遍歷所有可能包含目標值的位置。

證明
設當前位置為 (i, j),目標值為 target

  1. 如果 matrix[i][j] == target:找到目標,返回true
  2. 如果 matrix[i][j] > target
    • 由于第j列是遞增的,matrix[k][j] ≥ matrix[i][j] > target (對所有k > i)
    • 因此第j列的下方所有元素都大于target
    • 可以安全地排除第j列,向左移動:j--
  3. 如果 matrix[i][j] < target
    • 由于第i行是遞增的,matrix[i][k] ≤ matrix[i][j] < target (對所有k < j)
    • 因此第i行的左方所有元素都小于target
    • 可以安全地排除第i行,向下移動:i++

終止性:每次操作都會減少一行或一列,最多執行m+n次操作。

完整性:如果目標值存在,必然會被找到;如果不存在,會遍歷所有可能位置后返回false。

時間復雜度分析

定理:右上角搜索法的時間復雜度為O(m + n)。

證明

  • 設矩陣大小為m×n
  • 初始位置:(0, n-1)
  • 每次操作:要么row++要么col--
  • row最多增加m次(從0到m-1)
  • col最多減少n次(從n-1到0)
  • 總操作次數≤m+n
  • 因此時間復雜度為O(m + n)

執行流程圖

空矩陣
非空矩陣
越界
在范圍內
相等
當前值 > target
當前值 < target
開始: 輸入matrix和target
檢查矩陣是否為空
返回 false
初始化位置 row=0, col=n-1
當前位置在矩陣范圍內?
返回 false
比較 matrix當前位置 與 target
返回 true
向左移動 col = col - 1
向下移動 row = row + 1

搜索路徑示意圖

搜索路徑說明
矩陣搜索過程
起點: 右上角 值=15
target < 15: 向左移動
繼續比較直到找到或越界
1 4 7 11 15
2 5 8 12 19
3 6 9 16 22
10 13 14 17 24
18 21 23 26 30

實際應用

  1. 數據庫查詢:在有序索引中快速定位記錄
  2. 圖像處理:在像素矩陣中搜索特定模式
  3. 游戲開發:在有序地圖中尋找特定坐標
  4. 數據挖掘:在多維有序數據集中查找目標
  5. 搜索引擎:在排序后的文檔矩陣中定位關鍵詞

算法優化技巧

1. 預處理優化

// 快速判斷target是否在矩陣范圍內
if target < matrix[0][0] || target > matrix[m-1][n-1] {return false
}

2. 邊界優化

// 檢查目標是否在某行的范圍內
func isInRowRange(row []int, target int) bool {return target >= row[0] && target <= row[len(row)-1]
}

3. 緩存優化

對于頻繁查詢,可以緩存查詢路徑:

type SearchPath struct {row, col intdirection string // "left" or "down"
}

擴展思考

  1. 三維矩陣:如何在三維有序矩陣中搜索?
  2. 部分有序:如果只有部分行或列有序怎么處理?
  3. 動態矩陣:矩陣元素會動態變化時的搜索策略
  4. 并行搜索:如何并行化搜索過程?
  5. 近似搜索:尋找最接近目標值的元素

測試用例設計

// 基礎測試用例
matrix1 := [][]int{{1,4,7,11,15},{2,5,8,12,19},{3,6,9,16,22},{10,13,14,17,24},{18,21,23,26,30}
}
target = 5true
target = 20false// 邊界測試
matrix2 := [][]int{{1}}
target = 1true
target = 2false// 極值測試
matrix3 := [][]int{{1,2,3},{4,5,6},{7,8,9}
}
target = 1true  (左上角)
target = 9true  (右下角)
target = 5true  (中心)
target = 10false (超出范圍)// 空矩陣測試
matrix4 := [][]int{}
target = 1false// 單行/單列測試
matrix5 := [][]int{{1,3,5,7,9}}
target = 5true
target = 6falsematrix6 := [][]int{{1},{3},{5},{7},{9}}
target = 5true
target = 6false

性能對比

矩陣大小右上角搜索逐行二分分治法暴力搜索
10×1019μs45μs67μs123μs
100×100198μs890μs1.2ms12.3ms
1000×10001.98ms12.5ms18.7ms1.23s

總結

搜索二維矩陣 II 是一道經典的有序矩陣搜索問題,核心在于充分利用矩陣的雙向有序性

最優解法右上角搜索法,具有以下優勢:

  1. 時間復雜度最優:O(m + n)
  2. 空間復雜度最優:O(1)
  3. 思路簡潔清晰:易于理解和實現
  4. 代碼簡潔:只需要幾行核心邏輯

這道題體現了算法設計中的重要思想:

  • 利用數據結構的特性優化搜索策略
  • 貪心選擇確定搜索方向
  • 剪枝優化減少無效搜索

完整題解代碼

package mainimport "fmt"// 方法一:右上角開始搜索(推薦)
// 時間復雜度:O(m + n),空間復雜度:O(1)
func searchMatrix(matrix [][]int, target int) bool {if len(matrix) == 0 || len(matrix[0]) == 0 {return false}row, col := 0, len(matrix[0])-1for row < len(matrix) && col >= 0 {if matrix[row][col] == target {return true} else if matrix[row][col] > target {col-- // 向左移動} else {row++ // 向下移動}}return false
}// 方法二:逐行二分查找
// 時間復雜度:O(m * log n),空間復雜度:O(1)
func searchMatrixBinarySearch(matrix [][]int, target int) bool {if len(matrix) == 0 || len(matrix[0]) == 0 {return false}for _, row := range matrix {if binarySearch(row, target) {return true}}return false
}// 二分查找輔助函數
func binarySearch(arr []int, target int) bool {left, right := 0, len(arr)-1for left <= right {mid := left + (right-left)/2if arr[mid] == target {return true} else if arr[mid] < target {left = mid + 1} else {right = mid - 1}}return false
}// 方法三:分治法
// 時間復雜度:O(n^log?3) ≈ O(n^1.58),空間復雜度:O(log n)
func searchMatrixDivideConquer(matrix [][]int, target int) bool {if len(matrix) == 0 || len(matrix[0]) == 0 {return false}return divideConquer(matrix, target, 0, 0, len(matrix)-1, len(matrix[0])-1)
}func divideConquer(matrix [][]int, target, row1, col1, row2, col2 int) bool {// 邊界條件if row1 > row2 || col1 > col2 {return false}// 如果區域只有一個元素if row1 == row2 && col1 == col2 {return matrix[row1][col1] == target}// 選擇中間元素midRow := (row1 + row2) / 2midCol := (col1 + col2) / 2if matrix[midRow][midCol] == target {return true} else if matrix[midRow][midCol] > target {// 在左上、左下、右上區域搜索return divideConquer(matrix, target, row1, col1, midRow-1, col2) ||divideConquer(matrix, target, midRow, col1, row2, midCol-1)} else {// 在右下、左下、右上區域搜索return divideConquer(matrix, target, midRow+1, col1, row2, col2) ||divideConquer(matrix, target, row1, midCol+1, midRow, col2)}
}// 測試函數
func runTests() {fmt.Println("=== 240. 搜索二維矩陣 II 測試 ===")// 測試用例1matrix1 := [][]int{{1, 4, 7, 11, 15},{2, 5, 8, 12, 19},{3, 6, 9, 16, 22},{10, 13, 14, 17, 24},{18, 21, 23, 26, 30},}target1 := 5expected1 := truefmt.Printf("\n測試用例1:\n")fmt.Printf("矩陣:\n")printMatrix(matrix1)fmt.Printf("目標值: %d\n", target1)fmt.Printf("期望結果: %t\n", expected1)result1_1 := searchMatrix(matrix1, target1)result1_2 := searchMatrixBinarySearch(matrix1, target1)result1_3 := searchMatrixDivideConquer(matrix1, target1)fmt.Printf("方法一結果: %t ?\n", result1_1)fmt.Printf("方法二結果: %t ?\n", result1_2)fmt.Printf("方法三結果: %t ?\n", result1_3)// 測試用例2matrix2 := matrix1target2 := 20expected2 := falsefmt.Printf("\n測試用例2:\n")fmt.Printf("矩陣: (同上)\n")fmt.Printf("目標值: %d\n", target2)fmt.Printf("期望結果: %t\n", expected2)result2_1 := searchMatrix(matrix2, target2)result2_2 := searchMatrixBinarySearch(matrix2, target2)result2_3 := searchMatrixDivideConquer(matrix2, target2)fmt.Printf("方法一結果: %t ?\n", result2_1)fmt.Printf("方法二結果: %t ?\n", result2_2)fmt.Printf("方法三結果: %t ?\n", result2_3)// 測試用例3:邊界情況matrix3 := [][]int{{1}}target3 := 1fmt.Printf("\n測試用例3(邊界情況):\n")fmt.Printf("矩陣: [[1]]\n")fmt.Printf("目標值: %d\n", target3)fmt.Printf("期望結果: true\n")result3 := searchMatrix(matrix3, target3)fmt.Printf("結果: %t ?\n", result3)// 測試用例4:空矩陣var matrix4 [][]inttarget4 := 1fmt.Printf("\n測試用例4(空矩陣):\n")fmt.Printf("矩陣: []\n")fmt.Printf("目標值: %d\n", target4)fmt.Printf("期望結果: false\n")result4 := searchMatrix(matrix4, target4)fmt.Printf("結果: %t ?\n", result4)fmt.Printf("\n=== 算法復雜度分析 ===\n")fmt.Printf("方法一(右上角搜索):時間 O(m+n), 空間 O(1) - 推薦\n")fmt.Printf("方法二(逐行二分):  時間 O(m*logn), 空間 O(1)\n")fmt.Printf("方法三(分治法):    時間 O(n^1.58), 空間 O(logn)\n")
}// 打印矩陣輔助函數
func printMatrix(matrix [][]int) {for _, row := range matrix {fmt.Printf("%v\n", row)}
}func main() {runTests()
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/915765.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/915765.shtml
英文地址,請注明出處:http://en.pswp.cn/news/915765.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

瘋狂星期四文案網第16天運營日記

網站運營第16天&#xff0c;點擊觀站&#xff1a; 瘋狂星期四 crazy-thursday.com 全網最全的瘋狂星期四文案網站 運營報告 昨日訪問量 昨日30多ip, 今天也差不多&#xff0c;同步上周下降了一些&#xff0c;感覺明天瘋狂星期四要少很多了&#xff0c;記得上周四700多ip&…

Linux系統基礎入門與配置指南

Linux基本概述與配置 一、我們為什么使用Linux&#xff08;Linux的優點&#xff09;開源與自由 免費&#xff1a; 無需支付許可費用&#xff0c;任何人都可以自由下載、安裝和使用。源代碼開放&#xff1a; 任何人都可以查看、修改和分發源代碼。這帶來了極高的透明度、安全性和…

如何刪除VSCode Marketplace中的publisher

網頁上并沒有提供刪除的按鈕&#xff0c;需要通過命令的形式刪除。 vsce delete-publisher [要刪除的名字]# 鍵入token # y 確認這里的token是之前在Azure DevOps中創建的token&#xff0c;忘了的話可以重建一個 刷新網頁看一下 成功刪除了。

Windows安裝git教程(圖文版)

Git 是一個分布式版本控制系統&#xff0c;用于跟蹤文件的變化&#xff0c;特別是在軟件開發中。它使得多個開發者可以在不同的機器上并行工作&#xff0c;然后將他們的改動合并在一起。是在開發過程中&#xff0c;經常會用到的一個工具。本章教程&#xff0c;主要介紹Windows上…

Remote Framebuffer Protocol (RFB) 詳解

RFC 6143 規范文檔&#xff1a;The Remote Framebuffer Protocol 文章目錄1. 引言2. 初始連接流程2.1 TCP連接建立2.2 協議版本協商2.3 安全握手3. 顯示協議機制3.1 核心概念3.2 像素格式4. 輸入協議4.1 鍵盤事件(KeyEvent)4.2 鼠標事件(PointerEvent)5. 協議消息詳解5.1 握手消…

從 DeepSeek-V3 到 Kimi K2:八種現代大語言模型架構設計

編譯&#xff1a;青稞社區Kimi 原文&#xff1a;https://magazine.sebastianraschka.com/p/the-big-llm-architecture-comparison 首發&#xff1a;https://mp.weixin.qq.com/s/lSM2jk1UxJVz1WllWYQ4aQ 自原始 GPT 架構開發以來已經過去了七年。乍一看&#xff0c;從 2019 年的…

linux驅動開發筆記--GPIO驅動開發

目錄 前言 一、設備樹配置 二、驅動編寫 三、用戶空間測試 總結 前言 開發平臺&#xff1a;全志A133&#xff0c;開發環境&#xff1a;linux4.9andrio10&#xff0c;開發板&#xff1a;HelperBoard A133_V2.5。 一、設備樹配置 打開板級設備樹配置文件&#xff0c;路徑&a…

騰訊iOA:企業軟件合規與安全的免費守護者

人們眼中的天才之所以卓越非凡&#xff0c;并非天資超人一等而是付出了持續不斷的努力。1萬小時的錘煉是任何人從平凡變成超凡的必要條件。———— 馬爾科姆格拉德威爾 目錄 一、為什么要使用騰訊iOA&#xff1f; 二、中小企業軟件合規痛點 三、騰訊iOA解決方案 3.1 核心技…

C#定時任務實戰指南:從基礎Timer到Hangfire高級應用

高效管理后臺作業&#xff0c;讓定時任務成為應用的可靠引擎 在C#應用開發中&#xff0c;定時任務是實現數據同步、報表生成、系統維護等后臺作業的核心技術。本文將深入探討C#生態中主流的定時任務解決方案&#xff0c;從基礎的內置Timer到強大的Quartz.NET和Hangfire框架&…

軟件開發、項目開發基本步驟

? 立項階段&#xff1a;項目定義、需求收集與分析、可行性分析、風險評估與規劃、項目團隊組建、制定項目計劃、獲取批準與支持。? 需求評審與分析&#xff1a;? 項目團隊&#xff08;包括產品經理、開發人員、測試人員等&#xff09;共同參與&#xff0c;明確項目的目標、功…

慢 SQL接口性能優化實戰

在對某電商項目進行接口性能壓測時&#xff0c;發現 /product/search 接口響應緩慢&#xff0c;存在明顯性能瓶頸。通過慢查詢日志排查和 SQL 優化&#xff0c;最終實現了接口響應速度的顯著提升。本文完整還原此次優化過程&#xff0c;特別強調操作步驟和問題分析過程&#xf…

【C#】在WinForms中實現控件跨TabPage共享的優雅方案

文章目錄一、問題背景二、基本實現方案1. 通過修改Parent屬性實現控件移動三、進階優化方案1. 創建控件共享管理類2. 使用用戶控件封裝共享內容四、方案對比與選擇建議五、最佳實踐建議六、完整示例代碼一、問題背景 在Windows窗體應用程序開發中&#xff0c;我們經常遇到需要…

Android Camera openCamera

由頭 今日調休&#xff0c;終于終于閑下來了&#xff0c;可以寫一下博客了&#xff0c;剛好打開自己電腦&#xff0c;就有四年前下的谷歌Android 12源碼&#xff0c;不是很舊&#xff0c;剛好夠用&#xff0c;不用再另外下載新源碼了&#xff0c;不得不感慨這時間過得真快啊~廢…

神經網絡——池化層

目錄 池化層 最大池化層 MaxPool2d 最大池化操作圖示 最大池化操作代碼演示 綜合代碼案例 池化層 池化層&#xff08;Pooling Layer&#xff09; 核心作用&#xff1a;通過降采樣減少特征圖尺寸&#xff0c;降低計算量&#xff0c;增強特征魯棒性。 1. 常見類型 …

Android 默認圖庫播放視頻沒有自動循環功能,如何添加2

Android 默認圖庫播放視頻沒有自動循環功能, 如何添加 按如下方式修改可以添加 開發云 - 一站式云服務平臺 --- a/packages/apps/Gallery2/src/com/android/gallery3d/app/MovieActivity.java +++ b/packages/apps/Gallery2/src/com/android/gallery3d/app/MovieActivity.java…

數字孿生賦能智慧能源電力傳輸管理新模式

在“雙碳”戰略和能源數字化轉型的雙重驅動下&#xff0c;智慧能源系統亟需更高效、精細和智能的管理手段。數字孿生技術作為融合物理世界與數字空間的橋梁&#xff0c;為電力傳輸系統的全生命周期管理提供了強有力的技術支撐。本文聚焦數字孿生在智慧能源電力傳輸中的應用&…

Jmeter的元件使用介紹:(二)線程組詳解

Jmeter線程組默認包含三種&#xff1a;線程組、setUp線程組、tearDown線程組。線程組之間的執行順序為&#xff1a;setUp線程組->線程組->tearDown線程組。多數情況都是選用線程組&#xff0c;setUp線程組用于做一些腳本的前置準備&#xff0c;比如&#xff1a;跨線程組設…

AI替代人工:浪潮中的沉浮與覺醒

當AlphaGo以4:1的比分戰勝圍棋大師李世石之時&#xff0c;人機博弈的疆界被重新劃定&#xff1b;當工廠車間里機械臂以驚人精度與不知疲倦的姿態取代了工人重復的手勢&#xff1b;當客服電話那頭響起的不再是溫存人聲&#xff0c;而成了準確但缺乏溫度的AI語音&#xff1b;當算…

數學建模--matplot.pyplot(結尾附線條樣式表格)

matplotlib.pyplot繪圖接口 1. 用法 導入模塊 import matplotlib.pyplot as plt import numpy as np # 用于生成示例數據繪制簡單圖表 # 生成數據 x np.linspace(0, 10, 100) y np.sin(x)# 創建圖形和坐標軸 plt.figure(figsize(8, 4)) # 設置圖表大小 plt.plot(x, y, …

NumPy 實現三維旋轉變換

在三維空間中,物體的旋轉變換是計算機圖形學、機器人學以及三維建模等領域中一個至關重要的操作。這種變換可以通過構造特定的旋轉矩陣并將其應用于三維點或向量來實現。本文將深入探討如何利用 NumPy 這一強大的 Python 科學計算庫來實現三維旋轉變換,從基本的數學原理到具體…