LeetCode Word Search II,leetcodeii
LeetCode Word Search II題目
思路
結合Trie和DFS即可。
用C寫真是虐心。
也不知道有沒有記憶體泄露。
如有,望指正。
代碼
struct TrieNode { char c; // sons for "abcdefghijklmnopqrstuvwxyz\0" struct TrieNode * son[27]; };struct TrieNode * trieCreate() { struct TrieNode * trieNode = (struct TrieNode*)malloc(sizeof(struct TrieNode)); trieNode->c = '\0'; memset(trieNode->son, 0, sizeof(trieNode->son)); return trieNode;}void insert(struct TrieNode * root, char * word) { if (*word == '\0') { root->son[26] = trieCreate(); // notice that '\0' is important. There's "abc\0" // in Trie doesn't mean there's a word "ab\0". root->son[26]->c = '\0'; return; } if (root->son[*word - 'a'] == NULL) { root->son[*word - 'a'] = trieCreate(); root->son[*word - 'a']->c = *word; insert(root->son[*word - 'a'], word + 1); } else { insert(root->son[*word - 'a'], word + 1); }}bool search(struct TrieNode * root, char * word) { if (*word == '\0') { // notice that '\0' is important. There's "abc\0" // in Trie doesn't mean there's a word "ab\0". if (root->son[26] != NULL) return true; else return false; } if (root->son[*word - 'a'] == NULL) { return false; } else { return search(root->son[*word - 'a'], word + 1); }}void trieFree(struct TrieNode* root) { if (root != NULL) { for (int i = 0; i < 26; i++) { trieFree(root->son[i]); } free(root); }}char * AnAns; // 一個答案char ** Ans; // 一組答案char ** Board; // 輸入的boardbool ** vis; // 是否訪問過int AnsSize; // 答案的數量int WordsSize; // 輸入的單詞數量int WordMaxLength; // 輸入的單詞的最大長度int LastWordSize = 0; // 上一次的輸入單詞數量int BoardRowSize, BoardColSize; // board的屬性int dir[4][2] = { -1, 0, 1, 0, 0, -1, 0, 1 }; // 四個方向struct TrieNode * ExistWords, *Root; // 前者為是否已經找到,後者為建立的Trievoid dfs(struct TrieNode * nowLevel, int pi, int pj, int p) { if (AnsSize >= WordsSize) return; // 如果答案數已經達到最大 if (p > WordMaxLength) return; // 如果位置超過了最長的單詞長度 if (nowLevel->son[26] != NULL) { // 如果找到了某個單詞的結尾 AnAns[p] = '\0'; // 更改結尾符 if (!search(ExistWords, AnAns)) { // 如果這個單詞沒有被找到過 insert(ExistWords, AnAns); // 那麼把它標記為找到過 strcpy(Ans[AnsSize++], AnAns); // 然後放入答案中 } } for (int k = 0; k < 4; k++) { int gi = pi + dir[k][0]; int gj = pj + dir[k][1]; // 如果在範圍內、沒有訪問過、在Trie中也有這個單詞字母,那就繼續DFS if (0 <= gi && gi < BoardRowSize && 0 <= gj && gj < BoardColSize && !vis[gi][gj] && nowLevel->son[Board[gi][gj] - 'a'] != NULL) { vis[gi][gj] = true; AnAns[p] = Board[gi][gj]; dfs(nowLevel->son[Board[gi][gj] - 'a'], gi, gj, p + 1); vis[gi][gj] = false; } }}char ** findWords(char ** board, int boardRowSize, int boardColSize, char ** words, int wordsSize, int * returnSize) { Root = trieCreate(); // 建立Trie ExistWords = trieCreate(); // 建立標記Trie Board = board; BoardRowSize = boardRowSize; BoardColSize = boardColSize; WordsSize = wordsSize; WordMaxLength = 0; AnsSize = 0; // 將所有單詞插入Trie for (int i = 0; i < wordsSize; i++) { int Length = strlen(words[i]); if (Length > WordMaxLength) WordMaxLength = Length; insert(Root, words[i]); } // 初始化vis vis = (bool**)malloc(sizeof(bool*) * boardRowSize); for (int i = 0; i < boardRowSize; i++) { vis[i] = (bool*)malloc(sizeof(bool) * (boardColSize)); for (int j = 0; j < boardColSize; j++) vis[i][j] = false; } // 把上一次使用的Ans數組free掉,並建立一個 for (int i = 0; i < LastWordSize; i++) free(Ans[i]); free(Ans); LastWordSize = WordsSize; Ans = (char**)malloc(sizeof(char*) * wordsSize); for (int i = 0; i < wordsSize; i++) { Ans[i] = (char*)malloc(sizeof(char) * (WordMaxLength + 1)); } AnAns = (char*)malloc(sizeof(char*) * (WordMaxLength + 1)); for (int i = 0; i < boardRowSize && !(AnsSize >= wordsSize); i++) { for (int j = 0; j < boardColSize; j++) { if (Root->son[board[i][j] - 'a'] != NULL) { vis[i][j] = true; AnAns[0] = board[i][j]; dfs(Root->son[board[i][j] - 'a'], i, j, 1); vis[i][j] = false; if (AnsSize >= wordsSize) break; } } } // free for (int i = 0; i < boardRowSize; i++) free(vis[i]); free(vis); free(AnAns); trieFree(Root); trieFree(ExistWords); *returnSize = AnsSize; return Ans;}