# 212. Word Search II
題目:<https://leetcode.com/problems/word-search-ii/>
解法:backtracking,並藉由字典樹當作剪枝條件跟終止條件,還可以記錄結果。
Python3:
``` python 3
class Trie:
def __init__(self):
self.children = dict()
self.isWord = False
self.word = ''
def insert(self, word: str) -> None:
cur = self
for c in word:
if c not in cur.children:
cur.children[c] = Trie()
cur = cur.children[c]
cur.isWord = True
cur.word = word
def search(self, word: str) -> bool:
cur = self
for c in word:
if c not in cur.children:
return False
cur = cur.children[c]
return cur.isWord
class Solution:
def findWords(self, board: list[list[str]], words: list[str]) -> list[str]:
def backtrack(x, y, trie):
if trie.isWord:
output.add(trie.word)
visited.add((x, y))
if x > 0 and (x-1, y) not in visited and board[x-1][y] in trie.children:
backtrack(x-1, y, trie.children[board[x-1][y]])
if x < m - 1 and (x+1, y) not in visited and board[x+1][y] in trie.children:
backtrack(x+1, y, trie.children[board[x+1][y]])
if y > 0 and (x, y-1) not in visited and board[x][y-1] in trie.children:
backtrack(x, y-1, trie.children[board[x][y-1]])
if y < n - 1 and (x, y+1) not in visited and board[x][y+1] in trie.children:
backtrack(x, y+1, trie.children[board[x][y+1]])
visited.remove((x, y))
return
trie = Trie()
for word in words:
trie.insert(word)
m = len(board)
n = len(board[0])
visited = set()
output = set()
for x in range(m):
for y in range(n):
if board[x][y] in trie.children:
backtrack(x, y, trie.children[board[x][y]])
return list(output)
if __name__ == '__main__':
# board = [["o", "a", "a", "n"], ["e", "t", "a", "e"], ["i", "h", "k", "r"], ["i", "f", "l", "v"]]
# words = ["oath", "pea", "eat", "rain"]
board = [["o","a","b","n"],["o","t","a","e"],["a","h","k","r"],["a","f","l","v"]]
words = ["oa","oaa"]
ans = Solution().findWords(board, words)
print(ans)
```
C:
``` c
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
typedef struct Trie{
struct Trie* children[26];
bool isWord;
char* word;
bool isFind;
} Trie;
Trie* trieCreate() {
Trie* obj = (Trie*)malloc(sizeof(Trie));
for (int i = 0; i < 26; i++)
obj->children[i] = NULL;
obj->isWord = false;
obj->isFind = false;
return obj;
}
void trieInsert(Trie* obj, char * word) {
Trie* cur = obj;
for (int i = 0; i < strlen(word); i++) {
int idx = word[i]-'a';
if (cur->children[idx] == NULL)
cur->children[idx] = trieCreate();
cur = cur->children[idx];
}
cur->isWord = true;
cur->word = word;
}
void trieFree(Trie* obj) {
for (int i = 0; i < 26; i++)
if (obj->children[i] != NULL)
trieFree(obj->children[i]);
free(obj);
}
char ** findWords(char** board, int boardSize, int* boardColSize, char ** words, int wordsSize, int* returnSize){
int m = boardSize, n = boardColSize[0];
int visited[12][12] = {};
void backtrack(int x, int y, Trie* trie) {
if (trie->isWord)
trie->isFind = true;
visited[x][y] = 1;
if (x > 0 && visited[x-1][y] == 0) {
int idx = board[x-1][y]-'a';
if (trie->children[idx] != NULL)
backtrack(x-1, y, trie->children[idx]);
}
if (x < m - 1 && visited[x+1][y] == 0) {
int idx = board[x+1][y]-'a';
if (trie->children[idx] != NULL)
backtrack(x+1, y, trie->children[idx]);
}
if (y > 0 && visited[x][y-1] == 0) {
int idx = board[x][y-1]-'a';
if (trie->children[idx] != NULL)
backtrack(x, y-1, trie->children[idx]);
}
if (y < n - 1 && visited[x][y+1] == 0) {
int idx = board[x][y+1]-'a';
if (trie->children[idx] != NULL)
backtrack(x, y+1, trie->children[idx]);
}
visited[x][y] = 0;
return;
}
Trie* trie = trieCreate();
for (int i = 0; i < wordsSize; i++)
trieInsert(trie, words[i]);
for (int x = 0; x < boardSize; x++)
for (int y = 0; y < boardColSize[x]; y++) {
int idx = board[x][y]-'a';
if (trie->children[idx] != NULL)
backtrack(x, y, trie->children[idx]);
}
char ** output = (char**)malloc(sizeof(char*) * wordsSize);
*returnSize = 0;
void dfs(Trie* trie) {
if (trie->isFind) {
output[(*returnSize)++] = trie->word;
}
for (int i = 0; i < 26; i++)
if (trie->children[i] != NULL) {
dfs(trie->children[i]);
}
}
dfs(trie);
trieFree(trie);
return output;
}
int main()
{
int boardSize = 4;
int * boardColSize = (int*)malloc(sizeof(int) * boardSize);
char ** board = (char**)malloc(sizeof(char*) * boardSize);
for (int i = 0; i < boardSize; i++) {
boardColSize[i] = 4;
board[i] = (char*)malloc(sizeof(char) * boardColSize[i]);
}
board[0][0] = 'o'; board[0][1] = 'a'; board[0][2] = 'b'; board[0][3] = 'n';
board[1][0] = 'o'; board[1][1] = 't'; board[1][2] = 'a'; board[1][3] = 'e';
board[2][0] = 'a'; board[2][1] = 'h'; board[2][2] = 'k'; board[2][3] = 'r';
board[3][0] = 'a'; board[3][1] = 'f'; board[3][2] = 'l'; board[3][3] = 'v';
char *words[] = {"oa", "oaa"};
int wordsSize = sizeof(words) / sizeof(words[0]);
int returnSize;
char ** ans = findWords(board, boardSize, boardColSize, words, wordsSize, &returnSize);
printf("%d\n", returnSize);
for (int i = 0; i < returnSize; i++)
printf("%s\n", ans[i]);
return 0;
}
```
###### tags: `leetcode` `string` `trie` `backtracking`