๐Ÿ‹ โšพ๏ธ ๐Ÿ’ป ๐ŸŽฌ ๐ŸŽฎ

coding_test

[ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค] ๊ฐ€์‚ฌ ๊ฒ€์ƒ‰ (ํŒŒ์ด์ฌ)

aeightchill 2025. 3. 5. 22:36
728x90

๐Ÿ—‚๏ธ   ๋ฌธ์ œ 

2020 KAKAO BLIND RECRUITMENT_๊ฐ€์‚ฌ ๊ฒ€์ƒ‰


 
 
 


๐Ÿ“Œ   Point

ํŠธ๋ผ์ด(Trie) ์ž๋ฃŒ๊ตฌ์กฐ

  • ๋‹จ์–ด์˜ ๊ธธ์ด๋ณ„๋กœ Trie ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ค์–ด์„œ ํšจ์œจ์ ์œผ๋กœ ์ฟผ๋ฆฌ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.
  • ์ •๋ฐฉํ–ฅ Trie์™€ ์—ญ๋ฐฉํ–ฅ Trie๋ฅผ ๋™์‹œ์— ์ดˆ๊ธฐํ™”ํ•˜๊ณ  ๋‹จ์–ด๋ฅผ ์‚ฝ์ž…ํ•œ๋‹ค.
    • ์ •๋ฐฉํ–ฅ Trie : ์ ‘๋ฏธ์‚ฌ์— "?"๊ฐ€ ์žˆ์„ ๋•Œ ์‚ฌ์šฉ
    • ์—ญ๋ฐฉํ–ฅ Trie : ์ ‘๋‘์‚ฌ์— "?"๊ฐ€ ์žˆ์„ ๋•Œ ์‚ฌ์šฉ

๐Ÿ“  ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ ์˜ˆ์‹œ

 

๐Ÿ“Ž  ์ž…๋ ฅ ๋‹จ์–ด

words = ["apple", "app", "bat"]

 

๐Ÿ“Ž  ๊ธธ์ด๋ณ„ Trie ์ดˆ๊ธฐํ™”

# ์ •๋ฐฉํ–ฅ Trie (tries)
tries = {
    3: Trie(),  # 3๊ธ€์ž ๋‹จ์–ด์šฉ Trie
    5: Trie()   # 5๊ธ€์ž ๋‹จ์–ด์šฉ Trie
}

# ์—ญ๋ฐฉํ–ฅ Trie (tries_reverse)
tries_reverse = {
    3: Trie(),
    5: Trie()
}

 

๐Ÿ“Ž  ์ •๋ฐฉํ–ฅ Trie ๊ตฌ์„ฑ
 

  • tries[3]์— "app", "bat" ์‚ฝ์ž….
  • tries[5]์— "apple" ์‚ฝ์ž….

    Trie ๊ตฌ์กฐ (์ •๋ฐฉํ–ฅ, ๊ธธ์ด 3)

        (root)
       /    \
      a      b
      |      |
      p      a
      |      |
      p      t

 
   
    Trie ๊ตฌ์กฐ (์ •๋ฐฉํ–ฅ, ๊ธธ์ด 5)

         (root)
            |
            a
            |
            p
            |
            p
            |
            l
            |
            e

 

๐Ÿ“Ž  ์—ญ๋ฐฉํ–ฅ Trie ๊ตฌ์„ฑ
 

  • tries_reverse[3]์— "ppa", "tab" ์‚ฝ์ž….
  • tries_reverse[5]์— "elppa" ์‚ฝ์ž….

    Trie ๊ตฌ์กฐ (์ •๋ฐฉํ–ฅ, ๊ธธ์ด 3)

        (root)
       /    \
      p      t
      |      |
      p      a
      |      |
      a      b

 
    Trie ๊ตฌ์กฐ (์ •๋ฐฉํ–ฅ, ๊ธธ์ด 5)

         (root)
            |
            e
            |
            l
            |
            p
            |
            p
            |
            a

 
 
 
 


๐Ÿ“„   ์ฝ”๋“œ

class TrieNode:
    def __init__(self):
        self.children = {}  # ์ž์‹ ๋…ธ๋“œ๋ฅผ ์ €์žฅํ•  ๋”•์…”๋„ˆ๋ฆฌ
        self.count = 0      # ํ˜„์žฌ ๋…ธ๋“œ๋ฅผ ๊ฒฝ์œ ํ•˜๋Š” ๋‹จ์–ด์˜ ์ˆ˜

class Trie:
    def __init__(self):
        self.root = TrieNode()  # ๋ฃจํŠธ ๋…ธ๋“œ ์ดˆ๊ธฐํ™”
    
    def insert(self, word):
        node = self.root
        for char in word:
            if char not in node.children:
                node.children[char] = TrieNode()
            node = node.children[char]
            node.count += 1
    
    def count_match(self, query):
        # ์ „์ฒด๊ฐ€ "?"์ธ ๊ฒฝ์šฐ, ๋ฃจํŠธ์˜ count๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
        if set(query) == {'?'}:
            return self.root.count
        
        node = self.root
        for char in query:
            if char == '?':
                break
            if char not in node.children:
                return 0
            node = node.children[char]
        
        return node.count if node else 0

def solution(words, queries):
    tries = {}         # ์ •๋ฐฉํ–ฅ Trie
    tries_reverse = {} # ์—ญ๋ฐฉํ–ฅ Trie
    length_words = {}  # ๊ธธ์ด๋ณ„ ๋‹จ์–ด ๊ฐœ์ˆ˜ ์ €์žฅ. {'๊ธธ์ด' : ๊ฐœ์ˆ˜}
    
    # ๋‹จ์–ด๋“ค์„ ์ •๋ฐฉํ–ฅ ๋ฐ ์—ญ๋ฐฉํ–ฅ Trie์— ์‚ฝ์ž…
    for word in words:
        length = len(word)
        
        # ๊ธธ์ด๋ณ„ ๋‹จ์–ด ๊ฐœ์ˆ˜ ์ €์žฅ
        length_words[length] = length_words.get(length, 0) + 1
        
        if length not in tries:
            tries[length] = Trie()
            tries_reverse[length] = Trie()
        
        tries[length].insert(word)
        tries_reverse[length].insert(word[::-1])
    
    # ๊ฐ ์ฟผ๋ฆฌ์— ๋Œ€ํ•ด ๋งค์นญ๋˜๋Š” ๋‹จ์–ด ์ˆ˜ ๊ณ„์‚ฐ
    result = []
    for query in queries:
        length = len(query)
        
        # ์ „๋ถ€ "?"๋กœ ์ด๋ฃจ์–ด์ง„ ๊ฒฝ์šฐ
        if set(query) == {'?'}:
            result.append(length_words.get(length, 0))
            continue
        
        # ์ ‘๋‘์‚ฌ์— "?"๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ
        if query[0] == '?':
            if length not in tries_reverse:
                result.append(0)
                continue
            
            reversed_query = query[::-1]
            match_count = tries_reverse[length].count_match(reversed_query)
            result.append(match_count)
        
        # ์ ‘๋ฏธ์‚ฌ์— "?"๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ
        else:
            if length not in tries:
                result.append(0)
                continue
            
            match_count = tries[length].count_match(query)
            result.append(match_count)
    
    return result

 
 
 
 


โœ๐Ÿป   ํ’€์ด

์‹œ๊ฐ„ ๋ณต์žก๋„ : O(NM + QM)

N: ๋‹จ์–ด์ˆ˜,  M: ๋‹จ์–ด ๊ธธ์ด,  Q: ์ฟผ๋ฆฌ ์ˆ˜

 

  1. ํด๋ž˜์Šค ๊ตฌ์กฐ
    • Class : TrieNode
      • Node
        • children : ๋‹ค์Œ ๋ฌธ์ž๋กœ ์—ฐ๊ฒฐ๋˜๋Š” ์ž์‹ ๋…ธ๋“œ๋ฅผ ์ €์žฅํ•˜๋Š” ๋”•์…”๋„ˆ๋ฆฌ
        • count     : ํ•ด๋‹น ๋…ธ๋“œ๊นŒ์ง€ ์˜ค๋Š” ๋‹จ์–ด์˜ ๊ฐœ์ˆ˜๋ฅผ ์ €์žฅ
    • Class : Trie
      • ํŠธ๋ผ์ด์˜ root ๋…ธ๋“œ๋ฅผ ์ดˆ๊ธฐํ™”ํ•œ๋‹ค.
      • insert(word)  :  ๋‹จ์–ด๋ฅผ ํŠธ๋ผ์ด์— ์‚ฝ์ž…ํ•œ๋‹ค.
        • ๊ฐ ๋ฌธ์ž๋งˆ๋‹ค ๋…ธ๋“œ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ํ•ด๋‹น ๊ฒฝ๋กœ์˜ count๋ฅผ 1์”ฉ ์ฆ๊ฐ€ํ•œ๋‹ค.
      • count_match(query)  :  ์ฟผ๋ฆฌ์™€ ๋งค์นญ๋˜๋Š” ๋‹จ์–ด์˜ ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
        • query๊ฐ€ "?"๋กœ๋งŒ ์ด๋ฃจ์–ด์ง„ ๊ฒฝ์šฐ, ํ•ด๋‹น ๊ธธ์ด์˜ ๋‹จ์–ด ๊ฐœ์ˆ˜๋ฅผ ๋ฐ”๋กœ ๋ฐ˜ํ™˜
        • "?" ๋ฌธ์ž๊ฐ€ ๋‚˜์˜ค๋ฉด query ๋ฌธ์ž ํƒ์ƒ‰์„ ์ค‘๋‹จ  โ†’   ๋…ธ๋“œ์˜ count๋ฅผ ๋ฐ˜ํ™˜ํ•˜์—ฌ ๋‹จ์–ด ์ˆ˜ ๊ณ„์‚ฐ
  2. ๋‹จ์–ด ์ฒ˜๋ฆฌ
    • ๊ธธ์ด๋ณ„๋กœ ๋‹จ์–ด๋ฅผ ์ฒ˜๋ฆฌ
    • ๋‹จ์–ด์˜ ๊ธธ์ด๋ฅผ ํ‚ค(length)๋กœ ํ•˜์—ฌ Trie๋ฅผ ๋™์ ์œผ๋กœ ์ƒ์„ฑํ•œ๋‹ค.
      • tries : ์ •๋ฐฉํ–ฅ Trie
      • tries_reverse : ์—ญ๋ฐฉํ–ฅ Trie
    • Trie์— ๋‹จ์–ด ์‚ฝ์ž…
      • (์ •๋ฐฉํ–ฅ) ๋ฌธ์ž์—ด ๊ทธ๋Œ€๋กœ
      • (์—ญ๋ฐฉํ–ฅ) ๋ฌธ์ž์—ด ๋’ค์ง‘์–ด์„œ
  3. ์ฟผ๋ฆฌ ์ฒ˜๋ฆฌ
    • ์ „๋ถ€ "?"์ธ ๊ฒฝ์šฐ
      • length_words์—์„œ ํ•ด๋‹น ๊ธธ์ด์˜ ๋‹จ์–ด ๊ฐœ์ˆ˜๋ฅผ ๋ฐ”๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
    • "?"๊ฐ€ ์•ž์— ๋ถ™๋Š” ๊ฒฝ์šฐ (์ ‘๋‘์‚ฌ)
      • ์—ญ๋ฐฉํ–ฅ ํŠธ๋ผ์ด(tries_reverse) ์‚ฌ์šฉ
      • ์ฟผ๋ฆฌ๋ฅผ ๋’ค์ง‘์–ด "?"๊ฐ€ ๋’ค์— ์œ„์น˜ํ•˜๋„๋ก ํ•œ๋‹ค.
        • ์˜ˆ๋ฅผ ๋“ค์–ด "??odo"์ธ ๊ฒฝ์šฐ, "odo??"๋กœ ๋ฐ”๊พผ๋‹ค.
      • ์ ‘๋‘์‚ฌ ๋ถ€๋ถ„๊นŒ์ง€ ํŠธ๋ผ์ด๋ฅผ ๋”ฐ๋ผ๊ฐ„ ํ›„ ํ•ด๋‹น ๋…ธ๋“œ์˜ count๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
    • "?"๊ฐ€ ๋’ค์— ๋ถ™๋Š” ๊ฒฝ์šฐ (์ ‘๋ฏธ์‚ฌ)
      • ์ •๋ฐฉํ–ฅ ํŠธ๋ผ์ด(tries) ์‚ฌ์šฉ
      • ์ ‘๋‘์‚ฌ ๋ถ€๋ถ„๊นŒ์ง€ ํŠธ๋ผ์ด๋ฅผ ๋”ฐ๋ผ๊ฐ„ ํ›„ ํ•ด๋‹น ๋…ธ๋“œ์˜ count๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
        • ์˜ˆ๋ฅผ ๋“ค์–ด "fro??"์ธ ๊ฒฝ์šฐ, '?' ์ „์ธ 'o'์˜ count๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

 

 
 
 
 
 
 

728x90