Algorithm Problem/Python

[python] ν”„λ‘œκ·Έλž˜λ¨ΈμŠ€ - 가사 검색(2020 KAKAO BLIND RECRUITMENT)

deo2kim 2020. 8. 31. 08:24
λ°˜μ‘ν˜•

πŸ€”λ¬Έμ œ ν•΄κ²°

1. Lv4... | 트라이 자료ꡬ쑰

2. 트라이 자료ꡬ쑰λ₯Ό κ΅¬μ„±ν•œλ‹€.( μ‰½κ²Œ λ§ν•˜μžλ©΄ dictμ•ˆμ— dictμ•ˆμ— dictμ•ˆμ— dict.... ꡬ쑰 )

λŒ€λž΅ μœ„μ˜ κ·Έλ¦Όκ³Ό 같은 ν˜•νƒœλ‘œ κ΅¬μ„±ν•˜κ²Œ λœλ‹€. 맨 μ•žμ˜ μˆ«μžλŠ” 길이가 5인 단어,  6인 단어

λ‹€μŒ f둜 μ‹œμž‘ν•˜λŠ” 단어 4개, rλ‘œμ‹œμž‘ν•˜λŠ” 단어 4개, o둜 μ‹œμž‘ν•˜λŠ” 단어3개, d둜 μ‹œμž‘ν•˜λŠ” 단어 1개... κ°€ μžˆλ‹€λŠ” 의미

4. μ°ΎλŠ”λ‹€...

λ§Œμ•½ 'fro??' 을 μ°ΎλŠ”λ‹€κ³  ν•˜μž

 (1) 길이가 5 인 곳으둜 λ“€μ–΄κ°„λ‹€

 (2) κ±°κΈ°μ„œ f 둜 λ“€μ–΄κ°„λ‹€. cntμ—λŠ” f둜 μ‹œμž‘ν•˜λŠ” 단어가 4κ°œμžˆλ‹€λŠ” 것을 μ €μž₯ν•œλ‹€.

 (3) r 둜 λ“€μ–΄κ°„λ‹€. cntμ—λŠ” r둜 μ‹œμž‘ν•˜λŠ” 단어가 4개 μžˆλ‹€λŠ” 것을 μ €μž₯ν•œλ‹€.

 (4) o 둜 λ“€μ–΄κ°„λ‹€. cntμ—λŠ” o둜 μ‹œμž‘ν•˜λŠ” 단어가 3개 μžˆλ‹€λŠ” 것을 μ €μž₯ν•œλ‹€.

 (5) ? λ₯Ό λ§Œλ‚˜λ©΄ cnt λ₯Ό 리턴.

 (6) fro 둜 μ‹œμž‘ν•˜λ©΄μ„œ 길이가 5인 λ‹¨μ–΄λŠ” λ§ˆμ§€λ§‰μ— μ €μž₯된 3κ°œμ΄λ‹€.

 

πŸ’¨ !!Tipν•˜μ§€λ§Œ μ΄λ ‡κ²Œλ§Œ ν•˜λ©΄ νš¨μœ¨μ„± 3λ²ˆμ—μ„œ ν‹€λ¦°λ‹€. μ΄μœ λŠ” 쿼리가 λͺ¨λ‘ '?'둜 κ΅¬μ„±λœ κ²½μš°κ°€ 있기 λ•Œλ¬Έ!!!!

해결법: λ‹¨μ–΄μ˜ κΈΈμ΄λŠ” μ΅œλŒ€ 1λ§ŒκΉŒμ§€μ΄λ‹€. 1λ§ŒκΉŒμ§€μ˜ 배열을 λ§Œλ“€κ³ , 각 λ‹¨μ–΄μ˜ κΈΈμ΄λ§ˆλ‹€ λͺ‡κ°œμΈμ§€ μ €μž₯

쿼리가 λͺ¨λ‘ '?'둜 κ΅¬μ„±λœ 단어가 λ‚˜μ˜€λ©΄ 찾지말고 λ¦¬μŠ€νŠΈμ— μ €μž₯ν•΄λ‘” 갯수λ₯Ό κΊΌλ‚Έλ‹€.

 

😎 트라이 ꡬ쑰λ₯Ό μ΄μš©ν•˜μ§€ μ•Šκ³  문자λ₯Ό μž˜λΌμ„œ ν•˜λ‚˜ν•˜λ‚˜ μ°Ύμ•„μ€˜λ„ νš¨μœ¨μ„± 3번빼고 λ‹€ 찾을 μˆ˜λŠ” μžˆλ‹€.

( len('asdf') λŠ” ν•œλ²ˆμ„ μ–Έν•˜κ³  κ·Έ 값을 써주자. 계속 μ €λ ‡κ²Œ 뢈러였면 효율 μ•ˆμ’‹λ‹€.

λ§Œμ•½ μ‹œκ°„μ΄ μ—†κ³  트라이ꡬ쑰λ₯Ό λͺ¨λ₯Έλ‹€λ©΄ λΆ€λΆ„μ μˆ˜λΌλ„ μ±™κ²¨λ³΄μž

 

 

πŸ’»μ†ŒμŠ€ μ½”λ“œ

from collections import defaultdict
from collections import deque


def insert(part_trie, word):
    copy_trie = part_trie
    q = deque(list(word))
    while q:
        char = q.popleft()
        if char not in copy_trie:
            copy_trie[char] = [0, {}]
        copy_trie[char][0] += 1
        copy_trie = copy_trie[char][1]


def find(trie, query):
    cnt = 0
    copy_trie = trie
    if len(copy_trie) == 0:
        return 0

    q = deque(list(query))

    while q:
        char = q.popleft()
        if char == "?":
            return cnt
        else:
            if char not in copy_trie:
                return 0
            cnt = copy_trie[char][0]
            copy_trie = copy_trie[char][1]

    return cnt


def solution(words, queries):
    answer = []
    # 트라이 자료ꡬ쑰 ν™œμš©ν•˜κΈ°!
    trie = defaultdict(dict)
    reversed_trie = defaultdict(dict)

    # !!!쿼리가 λͺ¨λ‘ λ¬ΌμŒν‘œμΈ 경우 μ‹œκ°„ μ΄ˆκ³Όκ°€ λ°œμƒν•˜λ―€λ‘œ, 문자 길이에 따라 갯수 μ €μž₯
    length_list = [0] * 10001

    # trie λ§Œλ“€κΈ°
    for word in words:
        length_word = len(word)
        length_list[length_word] += 1

        insert(trie[length_word], word)
        insert(reversed_trie[length_word], word[::-1])

    # μ°ΎκΈ°
    for query in queries:
        length_query = len(query)

        if query.count('?') == length_query:  # 쿼리가 λͺ¨λ‘ λ¬ΌμŒν‘œμΈ 경우
            answer.append(length_list[length_query])
            continue
        if query[0] == "?":  # λ¬ΌμŒν‘œλ‘œ μ‹œμž‘ν•˜λŠ” 쿼리
            answer.append(find(reversed_trie[length_query], query[::-1]))
        else:
            answer.append(find(trie[length_query], query))

    return answer


qqq = [
    [["frodo", "front", "frost", "frozen", "frame", "kakao"], ["fro??", "????o", "fr???", "fro???", "pro?"]]
]
for q1, q2 in qqq:
    print(solution(q1, q2))

 

πŸ“•λ¬Έμ œ 확인

좜처: ν”„λ‘œκ·Έλž˜λ¨ΈμŠ€

링크: https://programmers.co.kr/learn/courses/30/lessons/60060

 

μ½”λ”©ν…ŒμŠ€νŠΈ μ—°μŠ΅ - 가사 검색

 

programmers.co.kr

 


문제 μ„€λͺ…

[λ³Έ λ¬Έμ œλŠ” μ •ν™•μ„±κ³Ό νš¨μœ¨μ„± ν…ŒμŠ€νŠΈ 각각 μ μˆ˜κ°€ μžˆλŠ” λ¬Έμ œμž…λ‹ˆλ‹€.]

μΉœκ΅¬λ“€λ‘œλΆ€ν„° 천재 ν”„λ‘œκ·Έλž˜λ¨Έλ‘œ λΆˆλ¦¬λŠ” ν”„λ‘œλ„λŠ” μŒμ•…μ„ ν•˜λŠ” μΉœκ΅¬λ‘œλΆ€ν„° μžμ‹ μ΄ μ’‹μ•„ν•˜λŠ” λ…Έλž˜ 가사에 μ‚¬μš©λœ 단어듀 쀑에 νŠΉμ • ν‚€μ›Œλ“œκ°€ λͺ‡ 개 ν¬ν•¨λ˜μ–΄ μžˆλŠ”μ§€ κΆκΈˆν•˜λ‹ˆ ν”„λ‘œκ·Έλž¨μœΌλ‘œ κ°œλ°œν•΄ λ‹¬λΌλŠ” μ œμ•ˆμ„ λ°›μ•˜μŠ΅λ‹ˆλ‹€.
κ·Έ μ œμ•ˆ 사항 쀑, ν‚€μ›Œλ“œλŠ” μ™€μΌλ“œμΉ΄λ“œ λ¬Έμžμ€‘ ν•˜λ‚˜μΈ '?'κ°€ ν¬ν•¨λœ νŒ¨ν„΄ ν˜•νƒœμ˜ λ¬Έμžμ—΄μ„ λœ»ν•©λ‹ˆλ‹€. μ™€μΌλ“œμΉ΄λ“œ 문자인 '?'λŠ” κΈ€μž ν•˜λ‚˜λ₯Ό μ˜λ―Έν•˜λ©°, μ–΄λ–€ λ¬Έμžμ—λ„ λ§€μΉ˜λœλ‹€κ³  κ°€μ •ν•©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄ "fro??"λŠ” "frodo", "front", "frost" λ“±μ— λ§€μΉ˜λ˜μ§€λ§Œ "frame", "frozen"μ—λŠ” λ§€μΉ˜λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

가사에 μ‚¬μš©λœ λͺ¨λ“  단어듀이 λ‹΄κΈ΄ λ°°μ—΄ words와 찾고자 ν•˜λŠ” ν‚€μ›Œλ“œκ°€ λ‹΄κΈ΄ λ°°μ—΄ queriesκ°€ μ£Όμ–΄μ§ˆ λ•Œ, 각 ν‚€μ›Œλ“œ λ³„λ‘œ 맀치된 단어가 λͺ‡ κ°œμΈμ§€ μˆœμ„œλŒ€λ‘œ λ°°μ—΄μ— λ‹΄μ•„ λ°˜ν™˜ν•˜λ„λ‘ solution ν•¨μˆ˜λ₯Ό μ™„μ„±ν•΄ μ£Όμ„Έμš”.

가사 단어 μ œν•œμ‚¬ν•­

  • words의 길이(가사 λ‹¨μ–΄μ˜ 개수)λŠ” 2 이상 100,000 μ΄ν•˜μž…λ‹ˆλ‹€.
  • 각 가사 λ‹¨μ–΄μ˜ κΈΈμ΄λŠ” 1 이상 10,000 μ΄ν•˜λ‘œ 빈 λ¬Έμžμ—΄μΈ κ²½μš°λŠ” μ—†μŠ΅λ‹ˆλ‹€.
  • 전체 가사 단어 길이의 합은 2 이상 1,000,000 μ΄ν•˜μž…λ‹ˆλ‹€.
  • 가사에 동일 단어가 μ—¬λŸ¬ 번 λ‚˜μ˜¬ 경우 쀑볡을 μ œκ±°ν•˜κ³  wordsμ—λŠ” ν•˜λ‚˜λ‘œλ§Œ μ œκ³΅λ©λ‹ˆλ‹€.
  • 각 가사 λ‹¨μ–΄λŠ” 였직 μ•ŒνŒŒλ²³ μ†Œλ¬Έμžλ‘œλ§Œ κ΅¬μ„±λ˜μ–΄ 있으며, νŠΉμˆ˜λ¬Έμžλ‚˜ μˆ«μžλŠ” ν¬ν•¨ν•˜μ§€ μ•ŠλŠ” κ²ƒμœΌλ‘œ κ°€μ •ν•©λ‹ˆλ‹€.

검색 ν‚€μ›Œλ“œ μ œν•œμ‚¬ν•­

  • queries의 길이(검색 ν‚€μ›Œλ“œ 개수)λŠ” 2 이상 100,000 μ΄ν•˜μž…λ‹ˆλ‹€.
  • 각 검색 ν‚€μ›Œλ“œμ˜ κΈΈμ΄λŠ” 1 이상 10,000 μ΄ν•˜λ‘œ 빈 λ¬Έμžμ—΄μΈ κ²½μš°λŠ” μ—†μŠ΅λ‹ˆλ‹€.
  • 전체 검색 ν‚€μ›Œλ“œ 길이의 합은 2 이상 1,000,000 μ΄ν•˜μž…λ‹ˆλ‹€.
  • 검색 ν‚€μ›Œλ“œλŠ” 쀑볡될 μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.
  • 각 검색 ν‚€μ›Œλ“œλŠ” 였직 μ•ŒνŒŒλ²³ μ†Œλ¬Έμžμ™€ μ™€μΌλ“œμΉ΄λ“œ 문자인 '?' λ‘œλ§Œ κ΅¬μ„±λ˜μ–΄ 있으며, νŠΉμˆ˜λ¬Έμžλ‚˜ μˆ«μžλŠ” ν¬ν•¨ν•˜μ§€ μ•ŠλŠ” κ²ƒμœΌλ‘œ κ°€μ •ν•©λ‹ˆλ‹€.
  • 검색 ν‚€μ›Œλ“œλŠ” μ™€μΌλ“œμΉ΄λ“œ 문자인 '?'κ°€ ν•˜λ‚˜ 이상 포함돼 있으며, '?'λŠ” 각 검색 ν‚€μ›Œλ“œμ˜ 접두사 μ•„λ‹ˆλ©΄ 접미사 쀑 ν•˜λ‚˜λ‘œλ§Œ μ£Όμ–΄μ§‘λ‹ˆλ‹€.
    • 예λ₯Ό λ“€μ–΄ "??odo", "fro??", "?????"λŠ” κ°€λŠ₯ν•œ ν‚€μ›Œλ“œμž…λ‹ˆλ‹€.
    • λ°˜λ©΄μ— "frodo"('?'κ°€ μ—†μŒ), "fr?do"('?'κ°€ 쀑간에 있음), "?ro??"('?'κ°€ μ–‘μͺ½μ— 있음)λŠ” λΆˆκ°€λŠ₯ν•œ ν‚€μ›Œλ“œμž…λ‹ˆλ‹€.

μž…μΆœλ ₯ 예

wordsqueriesresult

["frodo", "front", "frost", "frozen", "frame", "kakao"] ["fro??", "????o", "fr???", "fro???", "pro?"] [3, 2, 4, 1, 0]

μž…μΆœλ ₯ μ˜ˆμ— λŒ€ν•œ μ„€λͺ…

  • "fro??"λŠ” "frodo", "front", "frost"에 λ§€μΉ˜λ˜λ―€λ‘œ 3μž…λ‹ˆλ‹€.
  • "????o"λŠ” "frodo", "kakao"에 λ§€μΉ˜λ˜λ―€λ‘œ 2μž…λ‹ˆλ‹€.
  • "fr???"λŠ” "frodo", "front", "frost", "frame"에 λ§€μΉ˜λ˜λ―€λ‘œ 4μž…λ‹ˆλ‹€.
  • "fro???"λŠ” "frozen"에 λ§€μΉ˜λ˜λ―€λ‘œ 1μž…λ‹ˆλ‹€.
  • "pro?"λŠ” λ§€μΉ˜λ˜λŠ” 가사 단어가 μ—†μœΌλ―€λ‘œ 0 μž…λ‹ˆλ‹€.
λ°˜μ‘ν˜•