|
| 1 | +/** |
| 2 | + * [풀이 개요] |
| 3 | + * - 시간복잡도 : O(N * M * 3^L) |
| 4 | + * (N, M은 격자 크기, L은 단어의 길이. 각 칸에서 사방 탐색 시 이전 칸을 제외한 3방향으로 최대 L번 재귀 호출) |
| 5 | + * - 공간복잡도 : O(N * M) |
| 6 | + * (N * M 크기의 visited 배열 및 최대 L 깊이의 재귀 호출 스택 사용) |
| 7 | + */ |
| 8 | +class Solution { |
| 9 | + // 세로(row), 가로(col) 이동을 위한 오프셋 |
| 10 | + // dy -> dRow (상하 이동), dx -> dCol (좌우 이동) |
| 11 | + int[] dRow = { 0, 1, 0, -1 }; |
| 12 | + int[] dCol = { 1, 0, -1, 0 }; |
| 13 | + |
| 14 | + public boolean exist(char[][] board, String word) { |
| 15 | + int maxRow = board.length; // 세로 길이 (limitY) |
| 16 | + int maxCol = board[0].length; // 가로 길이 (limitX) |
| 17 | + |
| 18 | + // visited 배열도 board와 동일하게 [row][col] 크기로 선언 |
| 19 | + boolean[][] visited = new boolean[maxRow][maxCol]; |
| 20 | + char startChar = word.charAt(0); |
| 21 | + |
| 22 | + for (int r = 0; r < maxRow; r++) { |
| 23 | + for (int c = 0; c < maxCol; c++) { |
| 24 | + if (startChar == board[r][c]) { |
| 25 | + // 첫 글자가 일치하면 백트래킹 시작 |
| 26 | + if (find(1, word.length(), r, c, maxRow, maxCol, board, word, visited)) { |
| 27 | + return true; |
| 28 | + } |
| 29 | + } |
| 30 | + } |
| 31 | + } |
| 32 | + |
| 33 | + return false; |
| 34 | + } |
| 35 | + |
| 36 | + public boolean find( |
| 37 | + int cursor, |
| 38 | + int len, |
| 39 | + int curRow, |
| 40 | + int curCol, |
| 41 | + int maxRow, |
| 42 | + int maxCol, |
| 43 | + char[][] board, |
| 44 | + String word, |
| 45 | + boolean[][] visited |
| 46 | + ) { |
| 47 | + // 기저 조건: 단어를 모두 완성한 경우 |
| 48 | + if (cursor >= len) { |
| 49 | + return true; |
| 50 | + } |
| 51 | + |
| 52 | + // 현재 좌표 방문 처리 |
| 53 | + visited[curRow][curCol] = true; |
| 54 | + |
| 55 | + for (int i = 0; i < 4; i++) { |
| 56 | + int nextRow = curRow + dRow[i]; |
| 57 | + int nextCol = curCol + dCol[i]; |
| 58 | + |
| 59 | + // 1. 격자 경계선 체크 |
| 60 | + if (nextRow < 0 || nextRow >= maxRow || nextCol < 0 || nextCol >= maxCol) { |
| 61 | + continue; |
| 62 | + } |
| 63 | + |
| 64 | + // 2. 방문하지 않았고, 다음 목표 문자와 일치하는지 체크 |
| 65 | + if (!visited[nextRow][nextCol]) { |
| 66 | + char nextChar = board[nextRow][nextCol]; |
| 67 | + |
| 68 | + if (word.charAt(cursor) == nextChar) { |
| 69 | + if (find(cursor + 1, len, nextRow, nextCol, maxRow, maxCol, board, word, visited)) { |
| 70 | + return true; |
| 71 | + } |
| 72 | + } |
| 73 | + } |
| 74 | + } |
| 75 | + |
| 76 | + // 탐색이 실패로 끝나면 현재 좌표 방문 해제 (Backtrack) |
| 77 | + visited[curRow][curCol] = false; |
| 78 | + |
| 79 | + return false; |
| 80 | + } |
| 81 | +} |
0 commit comments