算法學習筆記:7.Dijkstra 算法——從原理到實戰,涵蓋 LeetCode 與考研 408 例題

在計算機科學領域,圖論算法一直占據著重要地位,其中 Dijkstra 算法作為求解單源最短路徑問題的經典算法,被廣泛應用于路徑規劃、網絡路由等多個場景。無論是算法競賽、實際項目開發,還是計算機考研 408 的備考,Dijkstra 算法都是必須掌握的核心內容。

一、Dijkstra 算法的基本概念

Dijkstra 算法是由荷蘭計算機科學家 Edsger W. Dijkstra 在 1956 年提出的,用于解決帶權有向圖或無向圖中,從一個源點到其余各頂點的最短路徑問題,即單源最短路徑問題。

假設我們有一個帶權圖,圖中的節點表示不同的位置,邊表示位置之間的連接,邊上的權值代表從一個節點到另一個節點的距離或代價。Dijkstra 算法的目標就是找到從給定的源節點出發,到圖中其他所有節點的最短路徑。

若以節點 A 為源點,Dijkstra 算法會計算出從 A 到 B、C、D、E 各節點的最短路徑。

二、Dijkstra 算法的思想

Dijkstra 算法采用貪心策略,其核心思想是:從源點開始,每次從未確定最短路徑的節點中,選擇距離源點最近的節點,并確定該節點的最短路徑,然后以該節點為中間點,更新其他節點到源點的距離。不斷重復這個過程,直到所有節點的最短路徑都被確定。

具體來說,Dijkstra 算法在執行過程中維護兩個集合:

  1. 已確定最短路徑的節點集合:初始時,該集合僅包含源節點。
  1. 未確定最短路徑的節點集合:包含圖中除源節點外的所有其他節點。

算法通過不斷從 “未確定最短路徑的節點集合” 中選取距離源點最近的節點,將其加入 “已確定最短路徑的節點集合”,并更新該節點鄰接節點到源點的距離。

以下是 Dijkstra 算法的詳細步驟:

  1. 初始化
    • 將源節點到自身的距離設為 0,即dist[source] = 0,其他節點到源點的距離設為無窮大,即dist[i] = ∞(i ≠ source)。
    • 初始化 “已確定最短路徑的節點集合” 為空,“未確定最短路徑的節點集合” 包含圖中所有節點。
  1. 循環迭代
    • 從 “未確定最短路徑的節點集合” 中選擇距離源點最近的節點u,將其加入 “已確定最短路徑的節點集合”。
    • 遍歷節點u的所有鄰接節點v,如果通過節點u到達節點v的距離比當前記錄的dist[v]更小,則更新dist[v],即dist[v] = dist[u] + weight(u, v),其中weight(u, v)表示邊(u, v)的權值。
  1. 重復步驟 2,直到 “未確定最短路徑的節點集合” 為空,此時dist數組中記錄的就是從源點到各個節點的最短路徑距離。

在初始狀態下,源點 S 到自身距離為 0,到其他節點距離為無窮大。第一輪選擇距離 S 最近的節點 B,更新 B 的鄰接節點 C 和 D 的距離。第二輪選擇距離 S 最近的節點 A,更新 A 的鄰接節點 D 的距離。第三輪選擇節點 D,此時所有節點的最短路徑都已確定。

三、Dijkstra 算法的解題思路

在實際應用中,使用 Dijkstra 算法解決問題時,通常需要以下幾個步驟:

  1. 構建圖模型:根據題目描述,將問題抽象為帶權圖,確定節點和邊,并為邊賦予相應的權值。
  1. 選擇源點:明確問題中指定的源節點,作為算法計算最短路徑的起點。
  1. 執行 Dijkstra 算法:按照上述算法步驟,計算從源點到其他所有節點的最短路徑。
  1. 處理結果:根據題目要求,對計算得到的最短路徑距離進行處理,例如返回特定節點的最短路徑、統計最短路徑的數量等。

四、LeetCode 例題及 Java 代碼實現

例題:網絡延遲時間(LeetCode 743)

有 n 個網絡節點,標記為 1 到 n。

給你一個列表 times,表示信號經過 有向 邊的傳遞時間。times[i] = (ui, vi, wi),其中 ui 是源節點,vi 是目標節點, wi 是一個信號從源節點傳遞到目標節點的時間。

現在,從某個節點 K 發出一個信號。需要多久才能使所有節點都收到信號?如果不能使所有節點收到信號,返回 -1 。

解題思路

本題可以將網絡節點抽象為圖的節點,邊的傳遞時間作為邊的權值,問題就轉化為求從節點K出發,到所有節點的最短路徑中最長的那個時間。如果存在某個節點無法到達,則返回-1。使用 Dijkstra 算法計算從節點K到其他節點的最短路徑距離,然后找出最大的距離值即可。

Java 代碼實現
import java.util .*;public class NetworkDelayTime {public int networkDelayTime(int[][] times, int n, int k) {// 構建鄰接表存儲圖List<List<int[]>> graph = new ArrayList<>();for (int i = 0; i <= n; i++) {graph.add(new ArrayList<>());}for (int[] time : times) {graph.get(time[0]).add(new int[]{time[1], time[2]});}// 初始化距離數組,將所有距離設為無窮大int[] dist = new int[n + 1];Arrays.fill(dist, Integer.MAX_VALUE);dist[k] = 0;// 標記節點是否已確定最短路徑boolean[] visited = new boolean[n + 1];// 優先隊列用于存儲未確定最短路徑的節點,按距離源點的距離排序PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> a[1] - b[1]);pq.offer(new int[]{k, 0});while (!pq.isEmpty()) {int[] node = pq.poll();int u = node[0];if (visited[u]) {continue;}visited[u] = true;for (int[] neighbor : graph.get(u)) {int v = neighbor[0];int w = neighbor[1];if (dist[u] != Integer.MAX_VALUE && dist[u] + w < dist[v]) {dist[v] = dist[u] + w;pq.offer(new int[]{v, dist[v]});}}}int maxTime = 0;for (int i = 1; i <= n; i++) {if (dist[i] == Integer.MAX_VALUE) {return -1;}maxTime = Math.max(maxTime, dist[i]);}return maxTime;}}

例題:解救人質(LeetCode 1306)

在一個 n x n 的網格中,每個單元格有兩種狀態:0 表示空單元格,1 表示人質押點。網格中有一個警衛,他的初始位置在 (0, 0),并且只能向下或向右移動。

警衛想要到達一個人質押點,然后再回到 (0, 0)。他每次移動一個單元格需要花費 1 單位時間。請你返回警衛從 (0, 0) 出發,到達任意一個人質押點并返回 (0, 0) 所需的最短時間。如果沒有可到達的人質押點,則返回 -1。

解題思路

本題可以將網格中的每個單元格看作圖的節點,相鄰單元格之間的邊權值為 1。由于警衛只能向下或向右移動,我們可以使用 Dijkstra 算法從起點(0, 0)出發,計算到所有人質押點的最短距離,再加上從人質押點返回起點的距離,取最小值作為結果。如果不存在人質押點,則返回-1。

Java 代碼實現
import java.util.PriorityQueue;public class MinimumTimeVisitingAllPoints {public int minimumTime(int[][] grid) {int n = grid.length;int[][] dist = new int[n][n];for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {dist[i][j] = Integer.MAX_VALUE;}}dist[0][0] = 0;PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> a[2] - b[2]);pq.offer(new int[]{0, 0, 0});int[][] directions = {{0, 1}, {1, 0}};while (!pq.isEmpty()) {int[] node = pq.poll();int x = node[0];int y = node[1];int d = node[2];if (d > dist[x][y]) {continue;}for (int[] dir : directions) {int newX = x + dir[0];int newY = y + dir[1];if (newX >= 0 && newX < n && newY >= 0 && newY < n) {int newDist = d + 1;if (newDist < dist[newX][newY]) {dist[newX][newY] = newDist;pq.offer(new int[]{newX, newY, newDist});}}}}int minTime = Integer.MAX_VALUE;boolean hasTarget = false;for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {if (grid[i][j] == 1 && dist[i][j] != Integer.MAX_VALUE) {hasTarget = true;minTime = Math.min(minTime, dist[i][j] * 2);}}}return hasTarget ? minTime : -1;}}

五、Dijkstra 算法與考研 408

在計算機考研 408 中,Dijkstra 算法是數據結構和算法部分的重要考點,主要涉及以下幾個方面:

  1. 圖的存儲結構:Dijkstra 算法的實現依賴于圖的存儲結構,常見的有鄰接矩陣和鄰接表。考研 408 中可能會考查不同存儲結構下 Dijkstra 算法的實現細節、空間復雜度和時間復雜度分析。例如,鄰接矩陣存儲圖時,Dijkstra 算法的時間復雜度為\(O(V^2)\)(\(V\)為節點數),而鄰接表存儲圖時,借助優先隊列優化后,時間復雜度可以降低到\(O((V + E) \log V)\)(\(E\)為邊數)。
  1. 貪心算法思想:Dijkstra 算法是貪心算法的典型應用,考研 408 中對貪心算法的理解和應用是考查重點。考生需要掌握貪心算法的設計要素,如貪心選擇性質和最優子結構性質,并能夠分析 Dijkstra 算法如何滿足這些性質,從而正確求解單源最短路徑問題。
  1. 算法正確性證明:雖然考研 408 中較少直接考查算法的正確性證明,但理解 Dijkstra 算法的正確性證明過程有助于深入掌握算法思想。證明過程通常基于數學歸納法,通過歸納假設和貪心選擇來逐步推導算法的正確性。
  1. 算法應用與變形:考研 408 中可能會出現基于 Dijkstra 算法的變形題目,例如在有負權邊的圖中(Dijkstra 算法不適用于有負權邊的圖,此時需使用 Bellman-Ford 算法或 Floyd 算法)進行拓展,或者結合其他知識點(如拓撲排序、動態規劃等)綜合考查。考生需要靈活運用 Dijkstra 算法的思想,分析和解決這類問題。

在備考過程中,建議考生通過做大量的練習題來鞏固對 Dijkstra 算法的理解,熟悉不同題型的解題思路,同時結合圖的存儲結構、貪心算法等相關知識點進行系統復習,提高綜合解題能力。

六、總結

Dijkstra 算法作為求解單源最短路徑問題的經典算法,無論是在實際應用還是計算機學科的學習中都具有重要意義。本文通過詳細介紹 Dijkstra 算法的基本概念、算法思想、解題思路,結合 LeetCode 例題與 Java 代碼實現,以及考研 408 的考點分析,幫助大家全面深入地理解和掌握該算法。

希望本文能夠幫助讀者更深入地理解Dijkstra 算法,并在實際項目中發揮其優勢。謝謝閱讀!


希望這份博客能夠幫助到你。如果有其他需要修改或添加的地方,請隨時告訴我。

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

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

相關文章

匯編 函數調用棧

前言 網上很多對函數棧的解釋&#xff0c;說的不是很清楚感覺&#xff0c;尤其是對到底是誰的棧&#xff0c;以及指令的微小但是很致命的細節沒說&#xff0c;特寫本文&#xff0c;一是幫助自己記憶&#xff0c;二是為了幫助大家&#xff0c;如有疏忽錯誤請指正。 核心概念 首先…

基于Apache MINA SSHD配置及應用

Apache MINA SSHD 是一個基于 Java 的 SSH 服務器和客戶端實現&#xff0c;它是 Apache MINA 項目的一部分&#xff0c;提供了完整的 SSH 協議支持。 主要特性 SSH 協議支持&#xff1a; 支持 SSH2 協議 兼容大多數 SSH 客戶端 支持多種加密算法和密鑰交換方法 服務器功能…

Excel 如何讓數據自動按要求排序或篩選?

讓數據按要求排序和篩選是Excel數據處理的基礎核心功能&#xff0c;也是進行有效分析前必做的準備工作。下面我們分開講解這兩個功能。 一、排序 (Sort)&#xff1a;讓數據井井有條 排序的目的是重新排列數據行的順序&#xff0c;以便更好地觀察和比較。 1. 快速單列排序 (最…

Django 安裝使用教程

一、Django 簡介 Django 是一個高級 Python Web 框架&#xff0c;鼓勵快速開發和簡潔實用的設計。它內置 ORM、認證系統、后臺管理、表單處理、路由控制等功能&#xff0c;廣泛用于開發企業級網站、內容管理系統、電商平臺等。 二、環境準備 2.1 安裝 Python Django 基于 Py…

前沿交叉:Fluent與深度學習驅動的流體力學計算體系

基礎模塊 流體力學方程求解 1、不可壓縮N-S方程數值解法&#xff08;有限差分/有限元/偽譜法&#xff09; Fluent工業級應用&#xff1a;穩態/瞬態流、兩相流仿真&#xff08;圓柱繞流、入水問題&#xff09; Tecplot流場可視化與數據導出 2、CFD數據的AI預處理 基于P…

五、Flutter動畫

目錄1. Flutter 中動畫的基本概念是什么&#xff1f;2. 解釋 AnimationController 和 Tween 的作用3. 如何實現一個補間&#xff08;Tween&#xff09;動畫&#xff1f;4. 什么是隱式動畫&#xff1f;舉例說明5. 如何實現自定義復雜動畫&#xff1f;1. Flutter 中動畫的基本概念…

全網唯一/Qt結合ffmpeg實現手機端采集攝像頭推流到rtsp或rtmp/可切換前置后置攝像頭/指定分辨率幀率

一、前言說明 之前已經實現了Qt結合ffmpeg在安卓上運行&#xff0c;所有在win上的功能&#xff0c;在安卓上都已經實現&#xff0c;比如編碼保存到MP4文件&#xff0c;正常解碼音視頻文件播放等&#xff0c;唯獨還差一個功能&#xff0c;盡管用的不多&#xff0c;但是還是有一…

Install Ubuntu 24.04 System

1.制作安裝鏡像盤&#xff08;U盤&#xff09; 下載rufus制作工具(網址&#xff1a;https://www.xiaomoxz.com/nexus/bi1/rufus4.shtml?bd_vid8643969197265870719&#xff09; 2. 設置U盤啟動&#xff1a; F2進入BIOS 3. Install Ubuntu 24.04 Ubuntu下載地址&#xff1a;…

solidjs 處理復雜類型的響應式

solidjs 處理復雜類型的響應式 在 solidjs 里響應式一般直接用 createSignal 就可以&#xff0c;但 createSignal 一般用于基礎數據類型。 雖然復雜類型也是可以使用&#xff0c;但基于起細粒度響應性的特性。 一般復雜的數據使用 createSignal 就不是那么友好了。 所以 cre…

爬蟲技術-獲取瀏覽器身份認證信息(如 Cookie、Token、Session 等)

方法一&#xff1a;通過瀏覽器開發者工具查看和提取 Cookie / Token &#x1f4cc; 示例場景&#xff1a; 你在使用一個網站時已經登錄了&#xff0c;想看看這個網站是如何保存你的身份憑證的。 &#x1f527; 操作過程&#xff1a; 打開瀏覽器&#xff08;例如 Chrome&#xf…

[密碼學實戰]GMT 0136-2024《密碼應用HTTP接口規范》解析

[密碼學實戰]GM/T 0136-2024《密碼應用HTTP接口規范》解析國家密碼管理局于2025年7月1日正式實施GM/T 0136-2024標準&#xff0c;該規范首次統一了密碼服務的HTTP接口設計&#xff0c;為國產密碼技術的規模化應用鋪平道路。本文結合標準原文&#xff0c;深入剖析其技術細節并給…

Docker 國內鏡像列表(免費長期)

Docker 可用鏡像源列表&#xff08;7月1日更新-長期維護&#xff09;_dockerhub國內鏡像源列表-CSDN博客

BlenderFBXExporter 導出fbx被修改問題

1&#xff09; 解決增加A節點的問題 https://github.com/A-Ribeiro/CustomBlenderFBXExporter 2&#xff09;找出blendshape 不一致&#xff0c;生成blendshape key name映射map 文件compare.txt C:\Users\49938\Documents\DazToUnreal\zhang01\UpdatedFBX\zhang01_fix7.fbx…

AI時代下的IT服務管理轉型:趨勢、挑戰與破局之道

近年來&#xff0c;人工智能&#xff08;AI&#xff09;與自動化技術的迅猛發展&#xff0c;正以前所未有的速度重塑企業運營的各個層面。特別是在IT服務管理&#xff08;ITSM&#xff09;領域&#xff0c;AI的介入不僅提高了問題響應效率&#xff0c;也推動了組織從“被動響應…

三體融合實戰:Django+訊飛星火+Colossal-AI的企業級AI系統架構

目錄 技術棧關鍵詞&#xff1a;Django 5.0 訊飛星火4.0Ultra Colossal-AI 1.2 WebSocket 聯邦學習 ? 核心架構設計 &#x1f6e0;? 一、Django深度集成訊飛星火API&#xff08;免費版&#xff09; 1. 獲取API憑證 2. 流式通信改造&#xff08;解決高并發阻塞&#xff09…

多模態數據融合預警:從IoT傳感器到衛星監測的可視化方案升級

你有沒有想過&#xff0c;為什么有些城市在暴雨來臨時能提前數小時發布內澇預警&#xff0c;而有些地方卻只能“等水來了才反應”&#xff1f; 背后的關鍵&#xff0c;就是多模態數據融合預警系統——它把來自IoT傳感器、無人機、地面雷達、氣象站、甚至衛星的數據整合在一起&a…

面試八股---css

2、css 2.1 說說你對盒子模型的理解 是什么 當對一個文檔進行布局&#xff08;layout&#xff09;的時候&#xff0c;瀏覽器的渲染引擎會根據標準之一的 CSS 基礎框盒模型&#xff08;CSS basic box model&#xff09;&#xff0c;將所有元素表示為一個個矩形的盒子&#xf…

day52-硬件學習之RTC及ADC

一、RTCRTC&#xff08;實時時鐘&#xff09;&#xff1a;非易失性在IMX6ULL內部SNVS&#xff08;安全的非易失性存儲器&#xff09;提供RTC功能&#xff1b;原理圖&#xff1a;二、ADC 2.1 基本概念ADC(模擬數字轉換器)&#xff1a;用于將連續變化的模擬信號轉換為離散的數字信…

Web 項目如何自動化測試?

Web 項目的自動化測試可以通過 UI自動化 和 接口自動化 結合實現&#xff0c;提高測試效率和覆蓋率。以下是關鍵方法和工具&#xff1a; 【自動化測試】從基礎到實戰基于Pytest自動化/python自動化的詳細教程&#xff01;1. UI自動化測試&#xff08;前端交互&#xff09; 適用…

Java連接阿里云MaxCompute例

要使用Java連接阿里云MaxCompute&#xff08;原名ODPS&#xff09;數據庫&#xff0c;您可以遵循以下步驟進行配置和編程&#xff1a; 1. 添加依賴 確保您的項目中包含了MaxCompute JDBC驅動的依賴。如果您使用Maven&#xff0c;可以在pom.xml中添加如下依賴&#xff1a; &l…