LeetCode刷題 -- 542. 01矩陣 基于 DFS 更新優化的多源最短路徑實現

LeetCode刷題 – 542. 01矩陣 基于 DFS 更新優化的多源最短路徑實現


題目描述簡述

給定一個 m x n 的二進制矩陣 mat,其中:

  • 每個元素為 0 或 1
  • 返回一個同樣大小的矩陣 ans,其中 ans[i][j] 表示 mat[i][j] 到最近 0 的最短曼哈頓距離

算法思路概覽

本題本質是一個多源最短路徑問題,我們需要從所有的 0 作為起點,向四周擴展,尋找每個 1 到任一 0 的最小距離。

經典的解法通常是 BFS。本實現采用改進的 DFS+DP 結合方式,通過自定義 updateAll() 函數遞歸地傳播距離,并利用 ans 數組記錄中間結果,控制條件防止冗余計算。


代碼解析與設計說明

關鍵宏定義

#define MY_MIN(a, b) ((a) < (b) ? (a) : (b))

簡單的最小值宏定義,用于更新當前單元格的最短距離。


核心遞歸函數 updateAll

void updateAll(int **mat, int rowsize, int colsize, int x, int y, int *ans, char *map_visited, int last_dis);

功能:

  • 遞歸探索四個方向的相鄰 1 節點
  • 如果當前節點未被訪問且不是 0,并且其距離不合理,則更新 ans 值并繼續傳播

關鍵邏輯詳解:

if (map_visited[x * colsize + y] == 1) return;
map_visited[x * colsize + y] = 1;if (mat[x][y] == 0) return;

然后判斷當前 ans[x][y] 是否需要更新:

if (abs(ans[x][y] - last_dis) > 1)

如果與傳入路徑的距離差值大于 1,說明不是“最優路徑”,需要更新為更近的 last_dis+1,并繼續傳播。


主函數 updateMatrix

int** updateMatrix(int** mat, int matSize, int* matColSize, int* returnSize, int** returnColumnSizes);

步驟拆解:

  1. 初始化變量
int row = matSize;
int col = matColSize[0];
int *ans = malloc(row * col * sizeof(int));
  1. 初始化輔助數組
char *map_visited = malloc(row * col);
  1. 遍歷所有格子
  • 若是 0,從它出發進行 updateAll 遞歸
  • 否則嘗試向上、向左推斷當前格子的最小距離
if (mat[x][y] == 0) {ans[x * col + y] = 0;...updateAll(...);
} else {if (x > 0) min_dis = MY_MIN(...);if (y > 0) min_dis = MY_MIN(...);ans[x * col + y] = min_dis;
}

舉個例子理解執行流程

輸入矩陣:

mat = [[0, 0, 1],[1, 1, 1],[1, 1, 0]]

執行后輸出矩陣:

ans = [[0, 0, 1],[1, 1, 1],[2, 1, 0]]

所有 0 首先被標記為 0,然后向周圍 1 遞歸傳播距離+1,遇到更遠的路徑時進行更新。

C代碼

#define MY_MIN(a, b) ((a) < (b) ? (a) : (b))void updateAll(int **mat, int rowsize, int colsize, int x, int y, int *ans, char *map_visited, int last_dis) {if (x < 0 || y < 0 || x >= rowsize || y >= colsize) {return;}if (map_visited[x * colsize + y] == 1) {return;}map_visited[x * colsize + y] = 1;if (mat[x][y] == 0) {return;}if (((ans[x * colsize + y] > last_dis) && ((ans[x * colsize + y] - last_dis) > 1)) || ((ans[x * colsize + y] < last_dis) && (last_dis - ans[x * colsize + y] > 1))) {ans[x * colsize + y] = last_dis + 1;updateAll(mat, rowsize, colsize, x - 1, y, ans, map_visited, last_dis + 1); // topupdateAll(mat, rowsize, colsize, x, y - 1, ans, map_visited, last_dis + 1); // leftupdateAll(mat, rowsize, colsize, x, y + 1, ans, map_visited, last_dis + 1); // right}
}/*** Return an array of arrays of size *returnSize.* The sizes of the arrays are returned as *returnColumnSizes array.* Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().*/
int** updateMatrix(int** mat, int matSize, int* matColSize, int* returnSize, int** returnColumnSizes) {int x = 0, y = 0;int row = matSize;int col = matColSize[0];int min_dis;*returnColumnSizes = (int *)malloc(sizeof(int) * row);memcpy(*returnColumnSizes, matColSize, sizeof(int) * row);*returnSize = row;int *ans = (int *)malloc(sizeof(int) * row * col);memset(ans, 0, sizeof(int) * row * col);char *map_visited = (char *)malloc(sizeof(char) * row * col);memset(map_visited, 0, sizeof(char) * row * col);for (x = 0; x < row; x++) {for (y = 0; y < col; y++) {min_dis = row - 1 + col - 1; //1. 注意點:初始化的距離值應該每個都一樣,一定要是最大距離值,方便當逼近右下角的情況,并且右下角不為0的情況;if (mat[x][y] == 0) {ans[x * col + y] = 0;memset(map_visited, 0, sizeof(char) * row * col);map_visited[x * col + y] = 1;updateAll(mat, row, col, x - 1, y, ans, map_visited, 0); // topupdateAll(mat, row, col, x, y - 1, ans, map_visited, 0); // leftupdateAll(mat, row, col, x, y + 1, ans, map_visited, 0); // right} else {if (x > 0) {min_dis = MY_MIN(ans[(x - 1) * col + y] + 1, min_dis);}if (y > 0) {min_dis = MY_MIN(ans[x * col + (y - 1)] + 1, min_dis);}ans[x * col + y] = min_dis;}}}// 構造二維 int** 返回結果int **result = (int **)malloc(sizeof(int *) * row);for (int i = 0; i < row; i++) {result[i] = ans + i * col;  // 指向 ans 中的每一行}free(map_visited);return result;
}

時間與空間復雜度分析

時間復雜度:

  • 最壞情況下,每個點可能被訪問多次(由于無記憶剪枝,可能存在重復遞歸)
  • 時間復雜度略高于 O(m × n),不如標準 BFS 穩定

空間復雜度:

  • ans 和 map_visited 占用 O(m × n) 空間
  • 遞歸棧空間最壞深度為 O(m + n)

該解法的優缺點總結

優點:

  • 結構清晰、代碼易理解
  • 利用 ans 記錄中間狀態實現 DP 剪枝
  • 對邊界控制處理較好

缺點:

  • 遞歸深度不受控,大數據易棧溢出
  • 沒有使用隊列優化,效率略遜于多源 BFS
  • 存在輕微冗余計算

改進建議

  1. 若數據量較大,應優先采用標準多源 BFS + 隊列方案,控制每個點僅訪問一次

  2. 若堅持遞歸風格,可考慮:

    • 加入更強的剪枝策略
    • 使用 stack 模擬遞歸避免棧溢出
    • 結合兩次掃描的 DP 法進一步優化初值

總結

該實現展示了一種不使用隊列、通過自定義遞歸傳播實現多源最短路徑的方式,適合對遞歸熟悉的開發者理解與優化,同時也為理解 BFS 與 DP 的結合提供了一個有趣的案例。雖然在最壞情況性能不如 BFS,但在面試或教學中極具啟發性。

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

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

相關文章

MySQL用戶遠程訪問權限設置

mysql相關指令 一. MySQL給用戶添加遠程訪問權限1. 創建或者修改用戶權限方法一&#xff1a;創建用戶并授予遠程訪問權限方法二&#xff1a;修改現有用戶的訪問限制方法三&#xff1a;授予特定數據庫的特定權限 2. 修改 MySQL 配置文件3. 安全最佳實踐4. 測試遠程連接5. 撤銷權…

如何使用 BPF 分析 Linux 內存泄漏,Linux 性能調優之 BPF 分析內核態、用戶態內存泄漏

寫在前面 博文內容為 通過 BCC 工具集 memleak 進行內存泄漏分析的簡單認知包括 memleak 腳本簡單認知,內核態(內核模塊)、用戶態(Java,Python,C)內存跟蹤泄漏分析 Demo理解不足小伙伴幫忙指正 ??,生活加油知其不可奈何而安之若命,德之至也。----《莊子內篇人間世》 …

谷歌Sign Gemma: AI手語翻譯,溝通從此無界!

嘿&#xff0c;朋友們&#xff01;想象一下&#xff0c;語言不再是交流的障礙&#xff0c;每個人都能順暢表達與理解。這聽起來是不是很酷&#xff1f;谷歌最新發布的Sign Gemma AI模型&#xff0c;正朝著這個激動人心的未來邁出了一大步&#xff01;它就像一位隨身的、不知疲倦…

全生命周期的智慧城市管理

前言 全生命周期的智慧城市管理。未來&#xff0c;城市將在 實現從基礎設施建設、日常運營到數據管理的 全生命周期統籌。這將避免過去智慧城市建設 中出現的“碎片化”問題&#xff0c;實現資源的高效配 置和項目的協調發展。城市管理者將運用先進 的信息技術&#xff0c;如物…

最新Spring Security實戰教程(十七)企業級安全方案設計 - 多因素認證(MFA)實現

&#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有堅忍不拔之志 &#x1f390; 個人CSND主頁——Micro麥可樂的博客 &#x1f425;《Docker實操教程》專欄以最新的Centos版本為基礎進行Docker實操教程&#xff0c;入門到實戰 &#x1f33a;《RabbitMQ》…

logstash拉取redisStream的流數據,并存儲ES

先說結論&#xff0c; window驗證logstash截至2025-06-06 是沒有原生支持的。 為啥考慮用redisStream呢&#xff1f;因為不想引入三方的kafka等組件&#xff0c; 讓服務部署輕量化&#xff0c; 所以使用現有的redis來實現&#xff0c; 為啥不用list呢&#xff1f; 已經用strea…

IEC 61347-1:2015 燈控制裝置安全通用要求詳解

IEC 61347-1:2015 燈控制裝置安全通用要求詳解 IEC 61347-1:2015《燈控制裝置 第1部分&#xff1a;一般要求和安全要求》是國際電工委員會&#xff08;IEC&#xff09;制定的關于燈控制裝置安全性能的核心基礎標準。它為各類用于啟動和穩定工作電流的燈控制裝置&#xff08;如…

26、跳表

在C標準庫中&#xff0c;std::map 和 std::set 是使用紅黑樹作為底層數據結構的容器。 紅黑樹是一種自平衡二叉搜索樹&#xff0c;能夠保證插入、刪除和查找操作的時間復雜度為O(log n)。 以下是一些使用紅黑樹的C標準庫容器&#xff1a; std::map&#xff1a;一種關聯容器&a…

LabVIEW音頻測試分析

LabVIEW通過讀取指定WAV 文件&#xff0c;實現對音頻信號的播放、多維度測量分析功能&#xff0c;為音頻設備研發、聲學研究及質量檢測提供專業工具支持。 主要功能 文件讀取與播放&#xff1a;支持持續讀取示例數據文件夾內的 WAV 文件&#xff0c;可實時播放音頻以監聽被測信…

JUC并發編程(二)Monitor/自旋/輕量級/鎖膨脹/wait/notify/鎖消除

目錄 一 基礎 1 概念 2 賣票問題 3 轉賬問題 二 鎖機制與優化策略 0 Monitor 1 輕量級鎖 2 鎖膨脹 3 自旋 4 偏向鎖 5 鎖消除 6 wait /notify 7 sleep與wait的對比 8 join原理 一 基礎 1 概念 臨界區 一段代碼塊內如果存在對共享資源的多線程讀寫操作&#xf…

Doris 與 Elasticsearch:誰更適合你的數據分析需求?

一、Doris 和 Elasticsearch 的基本概念 &#xff08;一&#xff09;Doris 是什么&#xff1f; Doris 是一個用于數據分析的分布式 MPP&#xff08;大規模并行處理&#xff09;數據庫。它主要用于存儲和分析大量的結構化數據&#xff08;比如表格數據&#xff09;&#xff0c…

使用Virtual Serial Port Driver+com2tcp(tcp2com)進行兩臺電腦的串口通訊

使用Virtual Serial Port Drivercom2tcp或tcp2com進行兩臺電腦的串口通訊 問題說明解決方案方案三具體操作流程網上教程軟件安裝拓撲圖準備工作com2tcp和tcp2com操作使用串口助手進行驗證 方案三存在的問題數據錯誤通訊延時 問題說明 最近想進行串口通訊的一個測試&#xff0c…

transformer和 RNN以及他的幾個變體區別 改進

Transformer、RNN 及其變體&#xff08;LSTM/GRU&#xff09;是深度學習中處理序列數據的核心模型&#xff0c;但它們的架構設計和應用場景有顯著差異。以下從技術原理、優缺點和適用場景三個維度進行對比分析&#xff1a; 核心架構對比 模型核心機制并行計算能力長序列依賴處…

CSS6404L 在物聯網設備中的應用優勢:低功耗高可靠的存儲革新與競品對比

物聯網設備對存儲芯片的需求聚焦于低功耗、小尺寸、高可靠性與傳輸效率&#xff0c;Cascadeteq 的 CSS6404L 64Mb Quad-SPI Pseudo-SRAM 憑借差異化技術特性&#xff0c;在同類產品中展現顯著優勢。以下從核心特性及競品對比兩方面解析其應用價值。 一、CSS6404L 核心產品特性…

go語言map擴容

map是什么&#xff1f; ?在Go語言中&#xff0c;map是一種內置的無序key/value鍵值對的集合&#xff0c;可以根據key在O(1)的時間復雜度內取到value&#xff0c;有點類似于數組或者切片結構&#xff0c;可以把數組看作是一種特殊的map&#xff0c;數組的key為數組的下標&…

2025年SDK游戲盾實戰深度解析:防御T級攻擊與AI反作弊的終極方案

一、引言&#xff1a;游戲安全的“生死防線” 2025年&#xff0c;全球游戲行業因DDoS攻擊日均損失3.2億元&#xff0c;攻擊峰值突破8Tbps&#xff0c;且70% 的攻擊為混合型&#xff08;DDoSCC&#xff09;。傳統高防IP因延遲高、成本貴、協議兼容性差&#xff0c;已無法滿足實…

【Linux】LInux下第一個程序:進度條

前言&#xff1a; 在前面的文章中我們學習了LInux的基礎指令 【Linux】初見&#xff0c;基礎指令-CSDN博客【Linux】初見&#xff0c;基礎指令&#xff08;續&#xff09;-CSDN博客 學習了vim編輯器【Linux】vim編輯器_linux vim insert-CSDN博客 學習了gcc/g【Linux】編譯器gc…

Web前端基礎

### 一、瀏覽器 火狐瀏覽器、谷歌瀏覽器(推薦)、IE瀏覽器 推薦谷歌瀏覽器原因&#xff1a; 1、簡潔大方,打開速度快 2、開發者調試工具&#xff08;右鍵空白處->檢查&#xff0c;打開調試模式&#xff09; ### 二、開發工具 核心IDE工具 1. Visual Studio Code (VS Code)?…

C++調試(肆):WinDBG分析Dump文件匯總

目錄 1.前言 2.WinDBG中常用的指令 3.分析異常時要關注的信息 4.心得 前言 本篇博客主要針如何使用WinDBG工具調試Dump文件的流程進行一個講解&#xff0c;具體捕獲的Dump文件也是前兩節例子中生成的Dump文件。 WinDBG中常用的指令 關于WinDBG調試時常用的指令主要分為以下幾種…

SOC-ESP32S3部分:33-聲學前端模型ESP-SR

飛書文檔https://x509p6c8to.feishu.cn/wiki/YnbmwtqI5iBwE3kHA7AcZ3yTnLf ESP-SR 是樂鑫官方開發的一個音頻組件&#xff0c;支持以下模塊&#xff1a; 聲學前端算法 AFE喚醒詞檢測 WakeNet命令詞識別 MultiNet語音合成&#xff08;目前只支持中文&#xff09; 組件地址&am…