1. 程式人生 > >leetcode-79-單詞搜索(用dfs解決)

leetcode-79-單詞搜索(用dfs解決)

搜索 dfs 這一 索引 算法 lse ats span 成功

題目描述:

給定一個二維網格和一個單詞,找出該單詞是否存在於網格中。

單詞必須按照字母順序,通過相鄰的單元格內的字母構成,其中“相鄰”單元格是那些水平相鄰或垂直相鄰的單元格。同一個單元格內的字母不允許被重復使用。

示例:

board =
[
  [‘A‘,‘B‘,‘C‘,‘E‘],
  [‘S‘,‘F‘,‘C‘,‘S‘],
  [‘A‘,‘D‘,‘E‘,‘E‘]
]

給定 word = "ABCCED", 返回 true.
給定 word = "SEE", 返回 true.
給定 word = "ABCB", 返回 false.

要完成的函數:

bool exist(vector<vector<char>>& board, string word)

說明:

1、這道題給定一個二維的vector,裏面存放著多個英文字符,還給了一個string,代表一個英文單詞。

要求判斷二維vector中存不存在一條路徑,連起來剛好就是string代表的單詞。

這條路徑不能使用重復的字符。

如果存在這樣一條路徑,那麽返回true,不存在就返回false。

2、這道題其實也就是深度優先搜索(DFS)的題目,熟悉這個算法的同學做這道題會很快。

我們還是照舊,舉個例子,大致說明一下思路。

board =
[
  [‘A‘,‘B‘,‘C‘,‘E‘],
  [‘S‘,‘F‘,‘C‘,‘S‘],
  [‘A‘,‘D‘,‘E‘,‘E‘]
]

給定的單詞是SEE,那麽我們首先在矩陣中找到S,有兩個,我們先試第一個,明顯第二個字母就對不上了,於是我們進入對第二個的查找。

在第二個周圍,我們先試S上方的E,然後再在這個E的周圍找另一個E,明顯沒有。

於是我們退一步,不試S上方的E了,我們嘗試S下方的E,可以,再在其附近找另一個E,也找得到。

我們在嘗試的時候,要註意這個字符之前有沒有使用過,這一步要做點處理。

從上述思路中,我們可以知道要用循環+遞歸的方法來做這道題。

先用循環找到第一個字符的索引,然後進入遞歸,如果遞歸成功找到了,那麽返回true。

如果不存在,那麽再循環找第一個字符的下一個索引,然後同樣進入遞歸,如果遞歸成功了,那麽返回true。

如果還是沒有,那麽再循環,一直循環,如果一直不滿足,最後返回false。

代碼如下(附詳解):

    bool dfs(vector<vector<char>>& board,int i,int j,string word,int index)
    {
        if(index==word.size())return true;//退出條件,滿足了說明成功找到
        int hang=board.size(),lie=board[0].size();
        if(i>0)//嘗試上方的字符
        {
            if(board[i-1][j]==word[index])
            {
                board[i-1][j]=‘!‘;//修改,避免重復使用
                if(dfs(board,i-1,j,word,index+1))//再度進入遞歸
                    return true;
                board[i-1][j]=word[index];//修改回去
            }
        }
        if(i<hang-1)//嘗試下方的字符
        {
            if(board[i+1][j]==word[index])
            {
                board[i+1][j]=‘!‘;
                if(dfs(board,i+1,j,word,index+1))
                    return true;
                board[i+1][j]=word[index];
            }
        }
        if(j>0)//嘗試左邊的字符
        {
            if(board[i][j-1]==word[index])
            {
                board[i][j-1]=‘!‘;
                if(dfs(board,i,j-1,word,index+1))
                    return true;
                board[i][j-1]=word[index];
            }
        }
        if(j<lie-1)//嘗試右邊的字符
        {
            if(board[i][j+1]==word[index])
            {
                board[i][j+1]=‘!‘;
                if(dfs(board,i,j+1,word,index+1))
                    return true;
                board[i][j+1]=word[index];
            }
        }
        return false;//如果嘗試四個方向都沒能找到,返回false
    }
    bool exist(vector<vector<char>>& board, string word) 
    {
        int hang=board.size(),lie=board[0].size();
        for(int i=0;i<hang;i++)
        {
            for(int j=0;j<lie;j++)
            {
                if(board[i][j]==word[0])//找到第一個字符的索引
                {
                    board[i][j]=‘!‘;//修改board中這個索引的值,避免重復使用
                    if(dfs(board,i,j,word,1))//進入遞歸,如果返回true,那麽找得到,最終返回true
                        return true;
                    board[i][j]=word[0];//如果遞歸沒成功找到,那麽把索引對應的字符給修改回去
                }
            }
        }
        return false;//一直沒能成功,說明不存在這樣一條路徑,返回false
    }

上述代碼實測20ms,beats 94.50% of cpp submissions。

leetcode-79-單詞搜索(用dfs解決)