|
| 1 | +/* |
| 2 | + Definition of a TrieNode: |
| 3 | +
|
| 4 | + data class TrieNode( |
| 5 | + var isWord: Boolean = false, |
| 6 | + var word: String? = null |
| 7 | + ) |
| 8 | +*/ |
| 9 | + |
| 10 | +fun findAllWordsOnABoard(board: Array<CharArray>, words: List<String>): List<String> { |
| 11 | + val root = TrieNode() |
| 12 | + // Insert every word into the trie. |
| 13 | + for (word in words) { |
| 14 | + var node = root |
| 15 | + for (c in word.toCharArray()) { |
| 16 | + if (c !in node.children) { |
| 17 | + node.children[c] = TrieNode() |
| 18 | + } |
| 19 | + node = node.children[c]!! |
| 20 | + } |
| 21 | + node.word = word |
| 22 | + } |
| 23 | + val res = mutableListOf<String>() |
| 24 | + // Start a DFS call from each cell of the board that contains a |
| 25 | + // child of the root node, which represents the first letter of a |
| 26 | + // word in the trie. |
| 27 | + for (r in 0 until board.size) { |
| 28 | + for (c in 0 until board[0].size) { |
| 29 | + if (board[r][c] in root.children) { |
| 30 | + dfs(board, r, c, root.children[board[r][c]], res) |
| 31 | + } |
| 32 | + } |
| 33 | + } |
| 34 | + return res |
| 35 | +} |
| 36 | + |
| 37 | +fun dfs(board: Array<CharArray>, r: Int, c: Int, node: TrieNode?, res: MutableList<String>) { |
| 38 | + // If the current node represents the end of a word, add the word to |
| 39 | + // the result. |
| 40 | + if (node?.word != null) { |
| 41 | + res.add(node.word!!) |
| 42 | + // Ensure the current word is only added once. |
| 43 | + node.word = null |
| 44 | + } |
| 45 | + val temp = board[r][c] |
| 46 | + // Mark the current cell as visited. |
| 47 | + board[r][c] = '#' |
| 48 | + // Explore all adjacent cells that correspond with a child of the |
| 49 | + // current TrieNode. |
| 50 | + val dirs = listOf(-1 to 0, 1 to 0, 0 to -1, 0 to 1) |
| 51 | + for ((dr, dc) in dirs) { |
| 52 | + val nextR = r + dr |
| 53 | + val nextC = c + dc |
| 54 | + if (isWithinBounds(board, nextR, nextC) && board[nextR][nextC] in node?.children.orEmpty()) { |
| 55 | + dfs(board, nextR, nextC, node?.children?.get(board[nextR][nextC]), res) |
| 56 | + } |
| 57 | + // Backtrack by reverting the cell back to its original character. |
| 58 | + board[r][c] = temp |
| 59 | + } |
| 60 | +} |
| 61 | + |
| 62 | +fun isWithinBounds(board: Array<CharArray>, r: Int, c: Int): Boolean { |
| 63 | + return r in board.indices && c in board[0].indices |
| 64 | +} |
0 commit comments