[오답노트] LeetCode #17 Letter Combinations of a Phone Number

Yongjun Park·2022년 2월 26일
0

PS(Problem Solving)

목록 보기
5/31

교훈
dfs 너무 어려워요... 많이 익혀야 할듯

문제

Given a string containing digits from 2-9 inclusive, return all possible letter combinations that the number could represent. Return the answer in any order.

2-9 사이의 숫자를 포함하는 문자열이 주어지면, 해당 숫자로 만들 수 있는 모든 문자 조합을 반환하라. 순서는 상관 없다.

A mapping of digit to letters (just like on the telephone buttons) is given below. Note that 1 does not map to any letters.

휴대폰 버튼처럼 생긴 아래의 그림에는 숫자 대 글자 대응이 나와 있으며, 1은 아무 문자에도 대응되지 않는다.

Example 1:

Input: digits = "23"
Output: ["ad","ae","af","bd","be","bf","cd","ce","cf"]

Example 2:

Input: digits = ""
Output: []

Example 3:

Input: digits = "2"
Output: ["a","b","c"]

Constraints:

  • 0 <= digits.length <= 4
  • digits[i] is a digit in the range ['2', '9'].

발상

Solution #1

어차피 digits의 길이는 0, 1, 2, 3, 4 밖에 될 수 없으니까 각 케이스별로 나누면 되잖아?

class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        letter = ['', 
                  '', 'abc', 'def', 
                  'ghi', 'jkl', 'mno', 
                  'pqrs', 'tuv', 'wxyz']
        
        result = []
        
        if len(digits) == 1:
            for c1 in letter[int(digits[0])]:
                result.append(c1)
                
        elif len(digits) == 2:
            for c1 in letter[int(digits[0])]:
                for c2 in letter[int(digits[1])]:
                    result.append(''.join([c1, c2]))
                    
        elif len(digits) == 3:
            for c1 in letter[int(digits[0])]:
                for c2 in letter[int(digits[1])]:
                    for c3 in letter[int(digits[2])]:
                        result.append(''.join([c1, c2, c3]))
                        
        elif len(digits) == 4:
            for c1 in letter[int(digits[0])]:
                for c2 in letter[int(digits[1])]:
                    for c3 in letter[int(digits[2])]:
                        for c4 in letter[int(digits[3])]:
                            result.append(''.join([c1, c2, c3, c4]))

		# len(digits) == 0이라면 그냥 빈 리스트 반환
        return result

통과는 한다.

Success
Runtime: 34 ms, faster than 71.70% of Python3 online submissions for Letter Combinations of a Phone Number.
Memory Usage: 13.9 MB, less than 91.67% of Python3 online submissions for Letter Combinations of a Phone Number.

그런데 당연히 추잡하다.

뭔가 일반화가 될 거 같은데, len(digits)에 따라 for문 중첩 개수를 다르게 해야 하니 좀처럼 일반화하기가 어렵다.

이런 건 어떻게 일반화해서 풀 수 있을까?

Solution #2

일반화가 더 어렵게 느껴졌던 이유 중 하나가, 문자열을 합치는 것에 대한 어색함 때문이었다.
'ab''c'를 추가하는 게 너무 어색했다.

그런데 생각해보면, python은 문자열 join을 매우 직관적으로 할 수 있는 방법이 있다.
'ab' + 'c' = 'abc'다!


풀이

class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        def dfs(index, path):
            if len(path) == len(digits):
                result.append(path)
                return
            for i in range(index, len(digits)):
                for j in dic[digits[i]]:
                    dfs(i+1, path+j) # path+j는 문자열 join이다!
            
        if not digits:
            return []
        dic = {
                '2': 'abc', 
                '3': 'def',
                '4': 'ghi',
                '5': 'jkl',
                '6': 'mno',
                '7': 'pqrs',
                '8': 'tuv',
                '9': 'wxyz'
            }
        result = []
        dfs(0, '')       
        return result

dfs에 path 정보를 갱신시키면서 함께 전달하는 방식이 매우 신박하다.

profile
추상화되었던 기술을 밑단까지 이해했을 때의 쾌감을 잊지 못합니다

0개의 댓글