문자가 있는 m x n
테이블에서 주어진 단어가 존재하는지 판별하는 문제다. 인접한 셀은 연결된 것으로 순차적으로 방문한 문자로 단어를 이룰 수 있으며, 방문한 셀은 재방문할 수 없다.
예를들어 위와 같은 테이블에서 단어 ABCCED
는 A
를 시작으로 B
, C
, C
, E
, D
를 거쳐 만들어질 수 있다.
class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
def findNext(y, x, count):
if count == len(word):
return True
temp = board[y][x]
board[y][x] = "#"
up = y-1 >= 0 and board[y-1][x] == word[count] and findNext(y-1, x, count + 1)
down = len(board) > y+1 and board[y+1][x] == word[count] and findNext(y+1, x, count + 1)
left = x-1 >= 0 and board[y][x-1] == word[count] and findNext(y, x-1, count + 1)
right = len(board[0]) > x+1 and board[y][x+1] == word[count] and findNext(y, x+1, count + 1)
board[y][x] = temp
return up or down or left or right
for y in range(len(board)):
for x in range(len(board[0])):
if board[y][x] == word[0] and findNext(y, x, 1):
return True
return False
테이블을 순회하며 주어진 단어의 시작 문자를 찾는다. 찾은경우 findNext()
함수를 호출한다.
findNext()
함수는 현재 위치 x
, y
와 지금까지 일치한 문자의 개수 count
를 매개변수로 갖는다.
True
를 반환한다.temp
에 해당 셀의 문자를 저장하고, #
로 대체한다.and
연산을 통해 최종 검사값을 업데이트하게끔 한다.temp
를 이용해 복구한다.or
연산을 한다.결과
박수 두개를 받았지만 어떻게하면 Runtime을 저렇게 줄일 수 있나 궁금해져 코드를 분석해봤다.
먼저 단어의 길이와 테이블에 있는 문자의 개수를 비교했다.
if len(word) > len(board) * len(board[0]): return False
False
를 반환한다.이후 단어와 테이블에 존재한 문자의 빈도를 확인했다.
count = Counter(sum(board, []))
for char, freq in Counter(word).items():
if count[char] < freq:
return False
False
를 반환한다.마지막으로 탐색 순서를 정했다.
if count[word[0]] > count[word[-1]]:
word = word[::-1]
최종 코드
class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
def findNext(y, x, count):
if count == len(word):
return True
temp = board[y][x]
board[y][x] = "#"
up = y-1 >= 0 and board[y-1][x] == word[count] and findNext(y-1, x, count + 1)
down = len(board) > y+1 and board[y+1][x] == word[count] and findNext(y+1, x, count + 1)
left = x-1 >= 0 and board[y][x-1] == word[count] and findNext(y, x-1, count + 1)
right = len(board[0]) > x+1 and board[y][x+1] == word[count] and findNext(y, x+1, count + 1)
board[y][x] = temp
return up or down or left or right
if len(word) > len(board) * len(board[0]): return False
count = Counter(sum(board, []))
for char, freq in Counter(word).items():
if count[char] < freq:
return False
if count[word[0]] > count[word[-1]]:
word = word[::-1]
for y in range(len(board)):
for x in range(len(board[0])):
if board[y][x] == word[0] and findNext(y, x, 1):
return True
return False
결과
최적화로 이렇게나 줄일 수 있다니..
앞으로는 문제를 풀고 최적화를 위해 고민하는 시간을 가져야겠다.