算法學習筆記:6.深度優先搜索算法——從原理到實戰,涵蓋 LeetCode 與考研 408 例題

在計算機科學領域,搜索算法是解決問題的重要工具,其中深度優先搜索(Depth-First Search,簡稱 DFS)憑借其簡潔高效的特性,在圖論、回溯、拓撲排序等眾多場景中發揮著關鍵作用。無論是 LeetCode 算法題,還是考研計算機專業基礎綜合(408)考試,深度優先搜索都是高頻考點。

深度優先搜索算法核心思路

深度優先搜索的基本思想是沿著一條路徑盡可能深地探索,直到無法繼續或達到目標狀態,然后回溯到上一個節點,繼續探索其他路徑,直至遍歷完所有可達節點。在圖結構或樹結構中,DFS 可以用來遍歷所有節點、尋找路徑、檢測連通性等。

1.1 算法實現方式

DFS 通常有兩種實現方式:遞歸和迭代(借助棧數據結構)。

  • 遞歸實現:利用函數調用棧,從起始節點開始,不斷遞歸訪問相鄰節點,當達到邊界條件(如訪問過的節點、無相鄰節點)時回溯。代碼簡潔直觀,但可能因遞歸深度過深導致棧溢出。
  • 迭代實現:手動維護一個棧,將起始節點入棧,每次取出棧頂節點,訪問其未訪問過的相鄰節點并將其入棧,直到棧為空。這種方式可避免棧溢出問題,適用于大規模數據。

1.2 算法流程

以圖結構為例,DFS 的基本流程如下:

  1. 選擇一個起始節點,標記為已訪問。
  1. 從起始節點出發,找到一個未訪問的相鄰節點,將其標記為已訪問,并以該節點為新的起始節點,遞歸執行步驟 2。
  1. 當當前節點的所有相鄰節點都已訪問時,回溯到上一個節點,繼續執行步驟 2。
  1. 重復步驟 2 和 3,直到所有可達節點都被訪問。

繪制出的 DFS 遞歸實現的流程圖:

為了更直觀地理解,假設我們有如下無向圖:

從節點 A 開始進行 DFS,訪問順序可能為 A -> B -> D -> E -> C(順序不唯一,取決于具體實現)。

LeetCode 例題實戰

例題 1:200. 島嶼數量

給你一個由 '1'(陸地)和 '0'(水)組成的的二維網格,請你計算網格中島嶼的數量。島嶼總是被水包圍,并且每座島嶼只能由水平方向和 / 或豎直方向上相鄰的陸地連接形成。此外,你可以假設該網格的四條邊均被水包圍。

示例 1:

輸入:grid = [

["1","1","1","1","0"],

["1","1","0","1","0"],

["1","1","0","0","0"],

["0","0","0","0","0"]

]

輸出:1

解題思路:使用 DFS 遍歷二維網格,當遇到'1'時,將其及其相鄰的'1'全部標記為已訪問(可以將'1'改為'0'),每完成一次 DFS,島嶼數量加 1。


public class NumIslands {public int numIslands(char[][] grid) {if (grid == null || grid.length == 0) {return 0;}int m = grid.length;int n = grid[0].length;int count = 0;for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if (grid[i][j] == '1') {dfs(grid, i, j);count++;}}}return count;}private void dfs(char[][] grid, int i, int j) {int m = grid.length;int n = grid[0].length;if (i < 0 || i >= m || j < 0 || j >= n || grid[i][j] == '0') {return;}grid[i][j] = '0';dfs(grid, i - 1, j);dfs(grid, i + 1, j);dfs(grid, i, j - 1);dfs(grid, i, j + 1);}}

例題 2:79. 單詞搜索

給定一個 m x n 二維字符網格 board 和一個字符串單詞 word 。如果 word 存在于網格中,返回 true ;否則,返回 false 。單詞必須按照字母順序,通過相鄰的單元格內的字母構成,其中 “相鄰” 單元格是那些水平相鄰或垂直相鄰的單元格。同一個單元格內的字母不允許被重復使用。

示例 1:

輸入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"

輸出:true

解題思路:從網格中的每個單元格開始進行 DFS,當當前字符與單詞當前字符匹配時,繼續向相鄰單元格遞歸搜索。為避免重復訪問,使用一個布爾數組記錄單元格是否已被訪問。如果找到匹配的路徑,返回true;遍歷完所有單元格仍未找到,則返回false。

public class WordSearch {public boolean exist(char[][] board, String word) {int m = board.length;int n = board[0].length;boolean[][] visited = new boolean[m][n];for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if (dfs(board, word, 0, i, j, visited)) {return true;}}}return false;}private boolean dfs(char[][] board, String word, int index, int i, int j, boolean[][] visited) {int m = board.length;int n = board[0].length;if (index == word.length()) {return true;}if (i < 0 || i >= m || j < 0 || j >= n || visited[i][j] || board[i][j] != word.charAt(index)) {return false;}visited[i][j] = true;boolean result = dfs(board, word, index + 1, i - 1, j, visited) ||dfs(board, word, index + 1, i + 1, j, visited) ||dfs(board, word, index + 1, i, j - 1, visited) ||dfs(board, word, index + 1, i, j + 1, visited);visited[i][j] = false;return result;}}

考研 408 例題分析

例題:已知一個無向連通圖的鄰接表存儲結構,編寫算法判斷圖中是否存在回路。

解題思路:利用 DFS 遍歷圖,在遍歷過程中記錄每個節點的前驅節點。當訪問到一個已訪問過的節點,且該節點不是當前節點的前驅節點時,說明存在回路。

import java.util.ArrayList;import java.util.List;class Graph {int V;List<List<Integer>> adj;Graph(int v) {V = v;adj = new ArrayList<>(v);for (int i = 0; i < v; i++) {adj.add(new ArrayList<>());}}void addEdge(int v, int w) {adj.get(v).add(w);adj.get(w).add(v);}boolean isCyclic() {boolean[] visited = new boolean[V];for (int i = 0; i < V; i++) {if (!visited[i]) {if (dfs(i, -1, visited)) {return true;}}}return false;}private boolean dfs(int v, int parent, boolean[] visited) {visited[v] = true;for (int i : adj.get(v)) {if (!visited[i]) {if (dfs(i, v, visited)) {return true;}} else if (i != parent) {return true;}}return false;}}public class CyclicGraph {public static void main(String[] args) {Graph g1 = new Graph(5);g1.addEdge(1, 0);g1.addEdge(0, 2);g1.addEdge(2, 1);g1.addEdge(0, 3);g1.addEdge(3, 4);if (g1.isCyclic()) {System.out.println("Graph contains cycle");} else {System.out.println("Graph does not contain cycle");}Graph g2 = new Graph(3);g2.addEdge(0, 1);g2.addEdge(1, 2);if (g2.isCyclic()) {System.out.println("Graph contains cycle");} else {System.out.println("Graph does not contain cycle");}}}

總結

深度優先搜索算法以其獨特的搜索策略,在解決各類問題中展現出強大的能力。通過 LeetCode 例題和考研 408 真題的實戰演練,我們不僅掌握了 DFS 在不同場景下的應用,還熟悉了其 Java 代碼實現。在實際編程和考研備考中,熟練運用 DFS 算法,能夠有效提升問題解決能力。后續可以進一步研究 DFS 與其他算法的結合應用,探索其在更復雜場景下的優化與拓展。

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


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

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

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

相關文章

vue create 和npm init 創建項目對比

以下是關于 vue create 和 npm init 的對比分析&#xff1a; 1. 定位與功能 vue create 定位&#xff1a;Vue 官方提供的腳手架工具&#xff0c;基于 Vue CLI&#xff0c;用于快速創建標準化的 Vue 項目&#xff0c;支持 Vue 2 和 Vue 3。功能&#xff1a;提供交互式配置&…

C++ bitset 模板類

bitset<256> 數據類型詳解 bitset<256> 是 C 標準庫中的一個模板類&#xff0c;用于處理固定大小的位集合&#xff08;Bit Set&#xff09;。它可以高效地操作和存儲二進制位&#xff0c;特別適合需要處理大量布爾標志或簡單計數的場景。 基本定義與特性 1. 模板參…

通信握手言和:PROFINET轉EtherCAT網關讓汽輪機振動數據“破壁”傳輸

某大型電廠的關鍵汽輪機設備采用EtherCAT振動傳感器進行實時監測&#xff0c;但由于工廠PLC振動分析系統基于PROFINET協議&#xff0c;數據無法直接接入&#xff0c;導致振動數據延遲、預警滯后&#xff0c;嚴重影響設備健康管理。傳統的人工巡檢和定期維護難以捕捉早期機械故障…

golang 中當 JSON 數據缺少結構體(struct)中定義的某些字段,會有異常嗎

目錄關鍵影響示例演示潛在問題與解決方案問題 1&#xff1a;邏輯錯誤&#xff08;零值干擾&#xff09;問題 2&#xff1a;忽略可選字段問題 3&#xff1a;第三方庫驗證最佳實踐總結在 Go 語言中&#xff0c;當 JSON 數據缺少結構體&#xff08;struct&#xff09;中定義的某些…

Fiddler 中文版怎么配合 Postman 與 Wireshark 做多環境接口調試?

現代項目中&#xff0c;開發、測試、預發布、生產環境往往分離配置&#xff0c;前端在開發過程中需要頻繁切換接口域名、驗證多環境表現。而接口升級或項目迭代時&#xff0c;還需要做回歸測試&#xff0c;確保老版本接口仍能兼容&#xff0c;避免線上事故。這些環節若僅靠代碼…

釘釘小程序開發技巧:getSystemInfo 系統信息獲取全解析

在釘釘小程序開發中&#xff0c;獲取設備系統信息是實現跨平臺適配和優化用戶體驗的關鍵環節。本文將深入解析 dd.getSystemInfo 接口的使用方法、技術細節與實際應用場景&#xff0c;幫助開發者高效應對多終端開發挑戰。一、接口功能與核心價值dd.getSystemInfo 是釘釘小程序提…

Java項目Maven配置JDK1.8全攻略

目錄 &#x1f9e9; 一、全局環境變量配置&#xff08;推薦系統級統一&#xff09; ?? 二、Maven全局配置&#xff08;多項目統一&#xff09; &#x1f4c2; 三、項目級配置&#xff08;推薦團隊協作&#xff09; &#x1f4bb; 四、IDE配置&#xff08;輔助驗證&#x…

使用tensorflow的線性回歸的例子(六)

波士頓房價 import matplotlib.pyplot as plt %matplotlib inline import tensorflow as tf import numpy as np from sklearn.datasets import load_boston import sklearn.linear_model as sk boston load_boston() features np.array(boston.data) labels np.arra…

YOLOv11深度解析:Ultralytics新一代目標檢測架構創新與實戰指南

?? 2024年Ultralytics重磅推出YOLOv11**:在精度與速度的平衡木上再進一步,參數減少22%,推理速度提升2%,多任務支持全面升級! ?? 一、YOLOv11核心創新:輕量化與注意力機制的完美融合 YOLOv11并非顛覆性重構,而是通過模塊級優化實現“少參數、高精度、快推理”的目標…

基于 SpringBoot+Vue.js+ElementUI 的 “花開富貴“ 花園管理系統設計與實現7000字論文

摘要 本論文詳細闡述了基于 SpringBoot、Vue.js 和 ElementUI 的 "花開富貴" 花園管理系統的設計與實現過程。該系統旨在為花園管理者提供高效、便捷的花園信息管理平臺&#xff0c;實現花卉信息、員工、客戶、訂單等全方位管理功能。論文首先分析了花園管理系統的研…

RESTful API 安裝使用教程

一、RESTful API 簡介 REST&#xff08;Representational State Transfer&#xff09;是一種基于 Web 的架構風格&#xff0c;RESTful API 是使用 HTTP 協議并遵循 REST 原則設計的 API 接口。其核心思想是&#xff1a;使用標準 HTTP 方法&#xff08;GET、POST、PUT、DELETE&…

【行云流水ai筆記】粗粒度控制:推薦CTRL、GeDi 細粒度/多屬性控制:推薦TOLE、GPT-4RL

TOLE模型完整啟動方法指南 TOLE (Token-level Optimization with Language Models) 是一種基于強化學習的可控文本生成方法&#xff0c;通過token級別的反饋實現對文本多個屬性的精確控制。以下是完整的啟動方法指南&#xff1a; 1. 環境準備 1.1 創建虛擬環境 conda creat…

【沉浸式解決問題】idea開發中mapper類中突然找不到對應實體類

目錄 一、問題描述二、場景還原三、原因分析四、解決方案 一、問題描述 mapper類繼承了mybatis-plus的BaseMapper&#xff0c;泛型需要填入實體類&#xff0c;但是不知怎么地突然實體類就報錯了&#xff0c;顯示沒有這個類 二、場景還原 實體類就是死活報錯找不到&#xff0c;所…

初學python的我開始Leetcode題11-2

提示&#xff1a;100道LeetCode熱題-11-1主要是二分查找相關&#xff0c;包括三題&#xff1a;搜索旋轉排序數組、尋找旋轉排序數組中的最小值、尋找兩個正序數組的中位數。由于初學&#xff0c;所以我的代碼部分僅供參考。前言上次的三道二分查找題較為基礎&#xff0c;主要是…

Python 數據分析與可視化 Day 12 - 建模前準備與數據集拆分

? 今日目標 掌握建模前常見準備步驟學會使用 train_test_split() 將數據劃分為訓練集和測試集理解特征&#xff08;X&#xff09;與標簽&#xff08;y&#xff09;的區分學習常見建模流程的輸入要求&#xff08;格式、維度&#xff09;&#x1f4d8; 一、建模前準備流程概覽 數…

Swagger 安裝使用教程

一、Swagger 簡介 Swagger 是一套開放源代碼的 API 文檔生成工具鏈&#xff0c;現歸屬于 OpenAPI 規范。它支持 RESTful API 的定義、生成、測試和文檔自動化。常見的使用工具包括 Swagger UI、Swagger Editor、Swagger Codegen 以及 SpringFox&#xff08;Spring 集成庫&…

【seismic unix相速度分析-頻散曲線】

介紹Seismic Unix Seismic Unix&#xff08;SU&#xff09;是一個開源的地震數據處理軟件包&#xff0c;主要用于地震數據的處理、分析和可視化。它由科羅拉多礦業學院的Center for Wave Phenomena開發&#xff0c;廣泛應用于學術研究和工業領域。SU提供了一系列命令行工具&am…

3.前端和后端參數不一致,后端接不到數據的解決方案

目錄 1.問題背景: (1).前端代碼: (2).后端代碼: (3).問題分析: [1]前端參數構造錯誤: [2].Api請求配置錯誤: 2.解決方案 (1).修改 role.js 中的 API 方法 (2).前端組件中的調用方式改成下面的而不是繼續拼接了 3.總結: 1.問題背景: 我在接口開發過程中&#xff0c;前…

SpringBoot:整合quartz實現定時任務-MisFire的處理

文章目錄 一、什么是MisFire二、MisFire發生的情況三、MisFire的補償策略四、代碼實現 一、什么是MisFire 簡單理解為&#xff1a;定時任務&#xff0c;所錯過的觸發 二、MisFire發生的情況 1、資源緊張&#xff0c;定時任務請求不到對應的線程。 2、調度器關閉。 3、設置定…

返回json,優雅處理轉換(如 0.85 → “85.00%“)

核心解決方案 通過 自定義序列化器 JsonSerialize 注解&#xff0c;實現 BigDecimal 到百分比字符串的自動轉換。 1.1 自定義序列化器代碼 java import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterx…