[每日一題] 79. Word Search

每日一題發表於2017-03-27

題目描述

本題難度:Medium

做題日期:2017年3月24日

本題地址: leetcode.com/problems/wo…

Given a 2D board and a word, find if the word exists in the grid.

The word can be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once.

For example,
Given board =

[
  ['A','B','C','E'],
  ['S','F','C','S'],
  ['A','D','E','E']
]
word = "ABCCED", -> returns true,
word = "SEE", -> returns true,
word = "ABCB", -> returns false.複製程式碼

題目分析

題意是要求我們求一個 MxN 的二位字母表中尋找是否有滿足給定單詞的字母集合,限制條件是字母集合是相鄰的。

這道題的特別之處在於:起始位置不確定 和 方向不定。一般的二維矩陣題目,都會給定一個起始位置,比如從左上角開始;也會限制搜尋的方向,比如只能向右和向下走。

由於起始位置不定,所以我們需要輪詢二維陣列的所有字母。方向不定,所以我們在暴力搜尋的時候,需要考慮邊界限制條件。

例子分析

假設我們要在如下的二維陣列中,尋找 SAD 字串 是否符合條件。如下圖一

[每日一題] 79. Word Search

假設我們已經確定了起始點為 S ,其位置座標是(1, 0) 。此時,我們需要判斷字元S(1,0) 周邊是否有第二個字元A,此時有四個可以選擇路徑:

  1. 向右走
    字元是 F(1, 1) ,不符合要求,捨棄
  2. 向上走
    字元是 A(0, 0),符合要求
  3. 向下走
    字串 A(2, 0),符合要求,但由於條件 2 已經滿足了,需要繼續遞迴
  4. 向右走
    超過了邊界限制,不符合要求

在上一個步驟,我們已經確定了 SA ,接下來確定 D。 其狀態如下圖二所示

[每日一題] 79. Word Search

根據上一個步驟的分析,在 A(0, 0) 我們也有四個選擇:

  1. 向右
    B(0, 1) 不等於 D ,排除
  2. 向上
    越界了,不符合要求,排除
  3. 向下
    S(1, 0) 已經訪問過了,也應該排除
  4. 向左
    越界了,不符合要求,排除

在上面的分析中的第3步,我們需要排除已經訪問過的字元,否則會進入死迴圈,這樣也會重複的選擇字元,不符合題目要求。

向上走的路徑不符合條件後,我們需要回溯到上一個起始點,也就是 S(1, 0) 位置,重新選擇路徑3:向下走 。

[每日一題] 79. Word Search

重複最先的分析,我們可以得到 SAD 是存在的,所以結果返回 True。

小結

從上面的分析,我們在寫程式碼的過程中,需要注意如下幾點

  1. 注意陣列越界的問題
  2. 如果當前位置的字母不滿足條件,需要回溯到上一個起始點的字母
  3. 需要記錄下訪問的路徑,防止重複訪問節點

解題思路

暴力方法

用一個MxN陣列 check 來標示訪問路徑,防止重複訪問,預設值是 false。當遍歷到位置(i,j) 的時候,將對應的 check[i][j] 設定成 true,表明該位置已經訪問過了,回溯後需要重置,將 check[i][j] 設定成 false。

時間複雜度是 O(MN4^K), 空間複雜度是 O(M*N)

[每日一題] 79. Word Search

優化空間

在上一個解題思路中,我們用了一個二維陣列 check 來儲存搜尋路徑,其空間複雜度是 O(MN)。其實是沒有必要的,我們在搜尋到(i, j) 的時候,將對應的 board[i][j] 設定成 *,並將原值儲存在一個 temp 變數中,在回溯後在恢復 board[i][j] 的值: board[i][j] = temp。

更好的方案是用二進位制操作 異或 的特性: X^Y = Z 一定有 Z^Y = X , 詳見最佳提交。

時間複雜度是 O(MN4^K), 空間複雜度是 O(1)

[每日一題] 79. Word Search

最佳提交

[每日一題] 79. Word Search

總結

  1. 可以使用陣列(比如二維陣列)儲存訪問過的節點,這樣可以防止重複訪問節點
  2. 空間優化的技巧:異或操作
  3. 回溯的時候需要重置路徑值

關於我們

每日一道演算法題是一個純粹的演算法學習社群:通過每天一起做一道演算法題來提升我們的演算法能力。

每日一題演算法群現在一共有3000位小夥伴:有來自北美和國內頂尖名校的本科生、研究生和博士生;也有來自國內外各大網際網路公司(Google, Facebook, 亞馬遜, 百度, 阿里, 騰訊等)的經驗豐富的開發者。大家聚集只為一個目的:每天一起學習演算法!

我們堅信:學習演算法是一種信仰!

長按下面的二維碼,關注每日一道演算法題公眾號,跟我們一起學習演算法!

[每日一題] 79. Word Search

相關文章