【LeetCode 熱題 100】79. 單詞搜索——回溯

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

文章目錄

  • 整體思路
  • 完整代碼
  • 時空復雜度
    • 時間復雜度:O(M * N * 3^L)
    • 空間復雜度:O(L)

整體思路

這段代碼旨在解決一個經典的二維網格搜索問題:單詞搜索 (Word Search)。其核心功能是判斷一個給定的單詞 word 是否存在于一個字符網格 board 中。構成單詞的路徑規則是:字母必須在網格中水平或垂直相鄰,并且同一個單元格的字母在路徑中不允許被重復使用。

該算法采用了 深度優先搜索(DFS) 結合 回溯(Backtracking) 的策略。其整體思路可以分解為以下幾個步驟:

  1. 主驅動邏輯(遍歷所有起點)

    • exist 方法是算法的入口。它通過兩層嵌套的 for 循環遍歷網格 board 中的每一個單元格 (i, j)
    • 這個遍歷的目的是將每一個單元格都視作單詞 word 的一個潛在 起始點
    • 對于每一個起點,它都會調用核心的 dfs 輔助函數來嘗試進行深度搜索。如果任何一次 dfs 調用返回 true,意味著找到了完整的單詞路徑,程序立即返回 true
    • 如果遍歷完所有可能的起點后,dfs 均未成功,則說明單詞不存在于網格中,程序最后返回 false
  2. 核心搜索邏輯(DFS 與回溯)

    • dfs(i, j, k, ...) 是一個遞歸函數,負責從單元格 (i, j) 開始,嘗試匹配 word 中從第 k 個字符開始的剩余部分。
    • 剪枝與基準情況
      • 失敗剪枝:如果當前單元格 (i, j) 超出邊界(在遞歸調用前檢查),或者其字符 board[i][j] 與目標字符 word[k] 不匹配,則此路不通,直接返回 false
      • 成功基準:如果當前字符匹配,并且這已經是單詞的最后一個字符(k == word.length - 1),則說明整個單詞已經成功匹配,返回 true
    • 遞歸與回溯
      • 標記(Marking):為了防止在同一路徑中重復使用單元格,在深入探索之前,代碼會將當前單元格 board[i][j] 的值臨時修改為一個特殊標記(如此代碼中的 0)。這相當于一個“正在訪問”的標記。
      • 探索(Exploration):接著,代碼會向當前單元格的四個相鄰方向(上、下、左、右)進行遞歸調用 dfs(x, y, k + 1, ...),嘗試匹配單詞的下一個字符。
      • 回溯(Backtracking):在四個方向的遞歸探索完成之后(無論成功還是失敗),必須將當前單元格 board[i][j] 的值恢復為其原始字符 word[k]。這是回溯算法的精髓,它確保了在探索其他起始點的路徑時,該單元格是可用的。
      • 如果四個方向的探索都沒有找到完整的路徑,則從當前點出發的搜索失敗,返回 false

完整代碼

class Solution {// 定義一個常量數組,用于表示四個方向的坐標偏移量:右、左、下、上private static final int[][] DIRECTION = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};/*** 在二維字符網格中查找是否存在一個給定的單詞。* @param board 二維字符網格* @param word  要查找的單詞* @return 如果單詞存在,返回 true;否則,返回 false。*/public boolean exist(char[][] board, String word) {// 將目標單詞轉換為字符數組,以提高后續字符訪問的效率char[] w = word.toCharArray();// 遍歷網格中的每一個單元格,將其作為單詞搜索的潛在起點for (int i = 0; i < board.length; i++) {for (int j = 0; j < board[0].length; j++) {// 從 (i, j) 開始進行深度優先搜索,嘗試匹配單詞的第一個字符 (k=0)if (dfs(i, j, 0, board, w)) {// 如果找到了一個完整的路徑,立即返回 truereturn true;}}}// 如果遍歷完所有可能的起點都未能找到單詞,則返回 falsereturn false;}/*** 深度優先搜索輔助函數。* @param i      當前搜索的行索引* @param j      當前搜索的列索引* @param k      當前要匹配的目標單詞中的字符索引* @param board  字符網格* @param word   目標單詞的字符數組* @return 如果從 (i, j) 出發能找到 word[k...] 的路徑,返回 true*/private boolean dfs(int i, int j, int k, char[][] board, char[] word) {// 剪枝:如果當前單元格的字符與目標字符不匹配,此路不通if (board[i][j] != word[k]) {return false;}// 成功基準:如果當前字符匹配,并且已是單詞的最后一個字符,則搜索成功if (k == word.length - 1) {return true;}// 關鍵【標記】步驟:將當前單元格標記為已訪問,防止在同一路徑中重復使用。// 這里用一個非字符值(如0)來標記,也可以用一個不會在 board 和 word 中出現的特殊字符。board[i][j] = 0; // 探索四個相鄰的方向for (int[] dir : DIRECTION) {int x = dir[0] + i;int y = dir[1] + j;// 檢查新坐標 (x, y) 是否在網格邊界內if (x >= 0 && x < board.length && y >= 0 && y < board[0].length) {// 對有效的相鄰單元格進行遞歸調用,嘗試匹配單詞的下一個字符 (k+1)if (dfs(x, y, k + 1, board, word)) {// 如果任意方向的遞歸探索成功,立即返回 truereturn true;}}}// 關鍵【回溯】步驟:恢復當前單元格的原始值。// 這樣,在回溯到上一個狀態后,其他分支的搜索路徑仍然可以使用此單元格。board[i][j] = word[k];// 如果所有方向都探索完畢,仍未找到匹配路徑,則返回 falsereturn false;}
}

時空復雜度

時間復雜度:O(M * N * 3^L)

  1. 外層循環exist 方法中的兩層 for 循環遍歷了整個網格,這部分是 M * N 次操作,其中 M 是行數,N 是列數。
  2. DFS 復雜度:對于每個起點,都會調用 dfs 函數。在 dfs 函數中,每次遞歸都會向最多 3 個新的方向探索(因為不能走回頭路,而修改 board 值的操作天然地防止了這一點)。
  3. 遞歸深度:遞歸的最大深度由單詞的長度 L 決定。
  4. 綜合分析
    • 在最壞的情況下,對于網格中的每個單元格 (M * N),我們都可能啟動一次深度優先搜索。
    • 每次搜索的計算量大致可以估算為 3^L,因為每一步都有最多3個選擇,持續 L 步。
    • 因此,總的時間復雜度是一個粗略的上限:O(M * N * 3^L),其中 L 是單詞 word 的長度。

空間復雜度:O(L)

  1. 主要存儲開銷:算法的額外空間開銷主要來自于遞歸調用棧。
  2. 遞歸深度dfs 函數的遞歸深度取決于正在匹配的單詞的長度。在最壞的情況下,當成功匹配到單詞的最后一個字母時,遞歸棧的深度會達到 L
  3. 其他變量
    • w = word.toCharArray(): 占用了 O(L) 的空間。
    • DIRECTION 數組:占用 O(1) 的常數空間。
    • 遞歸函數中的局部變量:占用 O(1) 空間。

綜合分析
遞歸棧的深度是空間復雜度的主要部分。因此,算法的空間復雜度為 O(L),其中 L 是單詞 word 的長度。

參考靈神

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

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

相關文章

ARM SMMUv3控制器注冊過程分析(八)

1.概述 ARM SMMUv3控制器初始化及設備樹分析&#xff08;七&#xff09;中描述了IOMMU控制器初始化過程。SMMU驅動最后調用iommu_device_register將其注冊到內核中&#xff0c;下面分析一下SMMU控制器注冊過程中都做了那些工作。 如下圖所示&#xff0c;SMMU控制器注冊過程中…

Idefics3:構建和更好地理解視覺-語言模型:洞察與未來方向

溫馨提示&#xff1a; 本篇文章已同步至"AI專題精講" Idefics3&#xff1a;構建和更好地理解視覺-語言模型&#xff1a;洞察與未來方向 摘要 視覺-語言模型&#xff08;VLMs&#xff09;領域&#xff0c;接收圖像和文本作為輸入并輸出文本的模型&#xff0c;正在快…

利用DeepSeek解決kdb+x進行tpch測試的幾個問題及使用感受

上文其實沒有成功運行tpch的22個標準查詢中的任何一個&#xff0c;因為DeepSeek原始給出的導入語句有錯&#xff0c;有一些表沒有導入。 1.解決類型及長度問題導致的插入tbl文件到內存表失敗。 kdbx的Reference card()提到的基本數據類型如下&#xff1a; Basic datatypes n …

SGLang 核心技術詳解

SGLang 作為一個高性能的 LLM 服務框架&#xff0c;通過一系列先進的優化技術實現了卓越的推理性能。下面詳細解釋其核心功能組件&#xff1a; 1. RadixAttention 用于前綴緩存 核心概念 RadixAttention 是 SGLang 獨創的前綴緩存機制&#xff0c;基于 Radix Tree&#xff08;基…

精密全波整流電路(四)

精密全波整流電路&#xff08;四&#xff09; 背景說明 [[精密半波整流電路|半波整流]]雖然能實現交直流信號的轉換&#xff0c;但是半波整流只能保留信號半個周期的能量&#xff0c;導致信號能量的利用率不高。 因此&#xff0c;在一些場合需要使用到全波整流電路。 同樣的&…

深入解讀Prometheus 2.33 Series Chunks壓縮特性:原理與實踐

深入解讀Prometheus 2.33 Series Chunks壓縮特性&#xff1a;原理與實踐 隨著監控指標規模不斷增長&#xff0c;Prometheus的本地TSDB存儲壓力日益增大。為提升存儲效率&#xff0c;Prometheus 2.33引入了Series Chunks壓縮特性&#xff0c;對時間序列數據在寫入和存儲時進行深…

SpringBoot整合Liquibase提升數據庫變更的可控性、安全性、自動化程度(最詳細)

為什么要使用liquibase?- 團隊協作與版本管理- 當多人&#xff08;或多個小組&#xff09;并行開發、對同一數據庫結構進行變更時&#xff0c;如果僅靠手寫 SQL 腳本&#xff0c;很 容易產生沖突或漏掉某些變更。- Liquibase 將所有 DDL/DML 操作以“changeset”形式納入源碼管…

數據寫入因為漢字引發的異常

spark 數據寫hive表,發生 查詢分區異常問題 異常: 25107124 19 26.49 ERROR Hive: MelaException(message.Exception thrown when execuling quey. S ELECT DISTINCT ‘org apache.hadop.hive melastore .modelMpartion As"NUCLEUS TYPE,AONCREATE TIME,AO.LAST ACCE…

Springboot項目實現將文件上傳到阿里云

Springboot項目實現將文件上傳到阿里云 一、概述二、具體步驟 2.1引入阿里云工具 首先先建utils包&#xff0c;然后引入AliOSSUtils類&#xff0c;如下&#xff1a; package com.hechixueyuan.forestfiredetectionsystem.utils;import com.aliyun.oss.OSS; import com.aliyun.o…

如何理解 TCP 是字節流協議?詳解

文章目錄一、面向字節流二、粘包問題應用層如何解決粘包問題&#xff1f;一、面向字節流 使用 TCP socket 進行網絡編程&#xff0c;Linux 內核會給每個 socket 都分配一個發送緩沖區和一個接收緩沖區 由于緩沖區的存在, TCP 讀寫不需要一一匹配&#xff0c;例如&#xff1a;…

面試問題總結——關于OpenCV(二)

最近小組在面試視覺算法工程師,順便整理了一波關于OpenCV的面試題目。 有些知識點也不深入,對于寫的不對的地方,歡迎指正。 目錄 20.像素梯度如何計算? 21.關于開運算和閉運算的理解 22.開運算和閉運算有什么優缺點? 23.圖像插值有哪些? 24.圖像金字塔的原理 25.邊緣檢測…

目標導向的強化學習:問題定義與 HER 算法詳解—強化學習(19)

目錄 1、目標導向的強化學習&#xff1a;問題定義 1.1、 核心要素與符號定義 1.2、 核心問題&#xff1a;稀疏獎勵困境 1.3、 學習目標 2、HER&#xff08;Hindsight Experience Replay&#xff09;算法 2.1、 HER 的核心邏輯 2.2、 算法步驟&#xff08;結合 DDPG 舉例…

2025 XYD Summer Camp 7.21 智靈班分班考 · Day1

智靈班分班考 Day1 時間線 8:00 在濱蘭實驗的遠古機房中的一個鍵盤手感爆炸的電腦上開考。開 T1&#xff0c;推了推發現可以 segment tree 優化 dp&#xff0c;由于按空格需要很大的力氣導致馬蜂被迫改變。后來忍不住了頂著疼痛按空格。8:30 過了樣例&#xff0c;但是沒有大樣…

基于多種主題分析、關鍵詞提取算法的設計與實現【TF-IDF算法、LDA、NMF分解、BERT主題模型】

文章目錄有需要本項目的代碼或文檔以及全部資源&#xff0c;或者部署調試可以私信博主一、項目背景二、研究目標與意義三、數據獲取與處理四、文本分析與主題建模方法1. 傳統方法探索2. 主題模型比較與優化3. 深度語義建模與聚類五、研究成果與應用價值六、總結與展望總結每文一…

MDC(Mapped Diagnostic Context) 的核心介紹與使用教程

關于日志框架中 MDC&#xff08;Mapped Diagnostic Context&#xff09; 的核心介紹與使用教程&#xff0c;結合其在分布式系統中的實際應用場景&#xff0c;分模塊說明&#xff1a; 一、MDC 簡介 MDC&#xff08;映射診斷上下文&#xff09; 是 SLF4J/Logback 提供的一種線程…

Linux隨記(二十一)

一、highgo切換leader&#xff0c;follow - 隨記 【待寫】二、highgo的etcd未授權訪問 - 隨記 【待寫】三、highgo的etcd未授權訪問 - 隨記 【待寫】3.2、etcd的metric未授權訪問 - 隨記 【待寫】四、安裝Elasticsearch 7.17.29 和 Elasticsearch 未授權訪問【原理掃描】…

Java環境配置之各類組件下載安裝教程整理(jdk、idea、git、maven、mysql、redis)

Java環境配置之各類組件下載安裝教程整理&#xff08;jdk、idea、git、maven、mysql、redis&#xff09;1.[安裝配置jdk8]2.[安裝配置idea]3.[安裝配置git]4.[安裝配置maven]5.[安裝配置postman]6.[安裝配置redis和可視化工具]7.[安裝配置mysql和可視化工具]8.[安裝配置docker]…

配置https ssl證書生成

1.可用openssl生成私鑰和自簽名證書 安裝opensslsudo yum install openssl -y 2.生成ssl證書 365天期限sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \-keyout /etc/ssl/private/nginx-selfsigned.key \-out /etc/ssl/certs/nginx-selfsigned.crt3、按照提示編…

編程語言Java——核心技術篇(四)集合類詳解

言不信者行不果&#xff0c;行不敏者言多滯. 目錄 4. 集合類 4.1 集合類概述 4.1.1 集合框架遵循原則 4.1.2 集合框架體系 4.2 核心接口和實現類解析 4.2.1 Collection 接口體系 4.2.1.1 Collection 接口核心定義 4.2.1.2 List接口詳解 4.2.1.3 Set 接口詳解 4.2.1.4…

GaussDB 數據庫架構師(八) 等待事件(1)-概述

1、等待事件概述 等待事件&#xff1a;指當數據庫會話(session)因資源競爭或依賴無法繼續執行時&#xff0c;進入"等待"狀態&#xff0c;此時產生的性能事件即等待事件。 2、等待事件本質 性能瓶頸的信號燈&#xff0c;反映CPU,I/O、鎖、網絡等關鍵資源的阻塞情況。…