1. 程式人生 > >LeetCode筆記——79單詞搜尋

LeetCode筆記——79單詞搜尋

題目:

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

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

示例:

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

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

思路:直接看了大神們的思路和程式碼,原文連結:https://blog.csdn.net/DERRANTCM/article/details/47248121

整個程式碼使用了回溯的思想,就是迭代加上迴圈。需要的資料結構包括一個記錄是否訪問過的陣列,一個記錄檢查到給定字元的哪個位置的陣列。首先遍歷陣列中的每一個元素,對於一個元素檢查該元素是否合法,即行列號是否合法,是否被訪問過,是否與對應word中的值相等,若這一切條件均滿足,則遞迴呼叫函式檢查上下左右的位置;如果搜尋的位置等於字串的長度,說明已經找到找到匹配的了, 如果沒有找到路徑(hasPath=false)就回溯。

程式碼:

class Solution {
   
    public boolean exist(char[][] board, String word) { // 【注意我們假定輸入的引數都是合法】
        // 訪問標記矩陣,初始值預設會設定為false
        boolean[][] visited = new boolean[board.length][board[0].length];
        // 以每一個位置為起點進行搜尋,找到一個路徑就停止
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[0].length; j++) {
                if (search(board, visited, i, j, word, new int[]{0})) {
                    return true;
                }
            }
        }
        return false;
    }
    /**
     * @param board   字元矩陣
     * @param visited 訪問標記矩陣
     * @param row     訪問的行號
     * @param col     訪問的列號
     * @param word    匹配的字串
     * @param idx     匹配的位置,取陣列是更新後的值可以被其它引用所見
     * @return
     */
    private boolean search(char[][] board, boolean[][] visited, int row, int col, String word, int[] idx) {
        // 如果搜尋的位置等於字串的長度,說明已經找到找到匹配的了
        if (idx[0] == word.length()) {
            return true;
        }
        boolean hasPath = false;
        // 當前位置合法
        if (check(board, visited, row, col, word, idx[0])) {
            // 標記位置被訪問過
            visited[row][col] = true;
            idx[0]++;
            // 對上,右,下,左四個方向進行搜尋
            hasPath = search(board, visited, row - 1, col, word, idx ) // 上
                || search(board, visited, row, col + 1, word, idx) // 右
                || search(board, visited, row + 1, col, word, idx) // 下
                || search(board, visited, row, col - 1, word, idx); // 左
            // 如果沒有找到路徑就回溯
            if (!hasPath) {
                visited[row][col] = false;
                idx[0]--;
            }
        }
        return hasPath;
    }
    /**
     * 判定訪問的位置是否合法
     *
     * @param board   字元矩陣
     * @param visited 訪問標記矩陣
     * @param row     訪問的行號
     * @param col     訪問的列號
     * @param word    匹配的字串
     * @param idx     匹配的位置
     * @return
     */
    public boolean check(char[][] board, boolean[][] visited, int row, int col, String word, int idx) {
        return row >= 0 && row < board.length // 行號合法
            && col >= 0 && col < board[0].length // 列號合法
            && !visited[row][col] // 沒有被訪問過
            && board[row][col] == word.charAt(idx);
        // 字元相等
    }
}

執行最快的的程式碼:

思路和上面的相同。

class Solution {
     int m;
    int n;

    public boolean exist(char[][] board, String word) {
        if (null == board || word == null || word.isEmpty()) {
            return false;
        }

        boolean[][] used = new boolean[board.length][board[0].length];


        m = board.length;
        n = board[0].length;

        char[] charArray = word.toCharArray();

        for(int i=0; i<m; i++) {
            for(int j=0; j<n;j++) {
                if (exist(board, used, charArray, i, j, 0)) {
                    return true;
                }
            }
        }

        return false;

    }

    private boolean exist(char[][] board, boolean[][] mem, char[] charArray, int i, int j, int index) {
        if (index == charArray.length) {
            return true;
        }

        if (i >= m || i < 0) {
            return false;
        }

        if (j >= n || j < 0) {
            return false;
        }


        if (mem[i][j] || board[i][j] != charArray[index]) {
            return false;
        }

        mem[i][j] = true;
        // up -> right -> down -> left
        boolean found = exist(board, mem, charArray, i - 1, j, index + 1)
                || exist(board, mem, charArray, i, j + 1, index + 1)
                || exist(board, mem, charArray, i + 1, j, index + 1)
                || exist(board, mem, charArray, i, j - 1, index + 1);


        // recover
        if (!found) mem[i][j] = false;


        return found;
    }
}