Skip to content

Design Add and Search Words Data Structure ๋ฌธ์ œ Trie ํ’€์ด ๋ณต์žก๋„ ๊ณ„์‚ฐ ๊ฐœ์„  ๊ฑด์˜ย #30

@yhkee0404

Description

@yhkee0404

Design Add and Search Words Data Structure ๋ฌธ์ œ Trie ํ’€์ด์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„์™€ ๊ณต๊ฐ„ ๋ณต์žก๋„๊ฐ€ ์ผ๋ถ€ O(26^w)์™€ O(2^w)๋ผ๊ณ  ๊ณ„์‚ฐ๋œ ๊ฒƒ๋ณด๋‹ค ๋” ์ค„์—ฌ์•ผ ๊ณ„์‚ฐ ๊ฐ€๋Šฅ์„ฑ ์„ค๋ช…์— ์œ ๋ฆฌํ•  ๊ฒƒ ๊ฐ™์•„์„œ ์ œ๋ณด ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

  1. ํ’€์ด 3: Trie 2

ํŠธ๋ผ์ด์˜ ๊ฐ ๋…ธ๋“œ์—์„œ ์ตœ์•…์˜ ๊ฒฝ์šฐ ์˜์–ด ์•ŒํŒŒ๋ฒณ ์†Œ๋ฌธ์ž `26`๊ฐœ๊ฐ€ ๋‹ค์Œ ๊ธ€์ž๊ฐ€ ๋  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ตœ๋Œ€ `26`๋ฒˆ์˜ ์žฌ๊ท€ ํ˜ธ์ถœ์ด ์ผ์–ด๋‚  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ํ˜ธ์ถœ ์Šคํƒ์€ ์ฐพ์œผ๋ ค๋Š” ๋‹จ์–ด์— ๋“ค์–ด์žˆ๋Š” ๊ธ€์ž์˜ ์ˆ˜์™€ ๋น„๋ก€ํ•ด์„œ ๊นŠ์–ด์ง€๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
๋”ฐ๋ผ์„œ `search()` ๋ฉ”์„œ๋“œ๋Š” ์‹œ๊ฐ„ ๋ณต์žก๋„๋Š” `O(26^w)`๊ฐ€ ๋˜๊ณ , ๊ณต๊ฐ„ ๋ณต์žก๋„๋Š” `O(w)`๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

O(26^w)๋ณด๋‹ค ๋” ๋‚ฎ์€ ์ƒํ•œ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
๋ฌธ์ œ์— ๋‹ค์Œ ์กฐ๊ฑด์ด ์žˆ์œผ๋ฏ€๋กœ ๊ฒฝ์šฐ๋ฅผ ๋‚˜๋ˆ„์–ด ์…€ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

There will be at most 2 dots in word for search queries.

dot์˜ ๊ฐœ์ˆ˜๊ฐ€ 0์ธ ์ตœ์„ ์˜ ๊ฒฝ์šฐ ํŠธ๋ผ์ด์˜ ๊ฐ ๋…ธ๋“œ์—์„œ ๋‹ค์Œ ๊ธ€์ž์˜ Branch๊ฐ€ 1๊ฐœ์ด๋ฏ€๋กœ ๋งค๋ฒˆ 1๋ฒˆ์˜ ์žฌ๊ท€ ํ˜ธ์ถœ์ด ์ผ์–ด๋‚ฉ๋‹ˆ๋‹ค.
์ฆ‰ O(w * 1^w) = O(w)์ž…๋‹ˆ๋‹ค.

dot์˜ ๊ฐœ์ˆ˜๊ฐ€ 1์ด๋ฉด w๋ฒˆ ์ค‘ 1๋ฒˆ์€ Branch๊ฐ€ ์ตœ์•…์˜ ๊ฒฝ์šฐ 26๊ฐœ์ผ ๋•Œ ๋‹ค์Œ ์žฌ๊ท€ ํ˜ธ์ถœ์ด 26๋ฒˆ ์ผ์–ด๋‚  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๋‚˜ ๊ทธ 1๋ฒˆ์„ ์ œ์™ธํ•œ ๋‚˜๋จธ์ง€ (w - 1)๋ฒˆ์€ Branch๊ฐ€ 1๊ฐœ๋ผ์„œ ์ด์ „๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋งค๋ฒˆ 1๋ฒˆ์˜ ์žฌ๊ท€ ํ˜ธ์ถœ์ด ์ผ์–ด๋‚ฉ๋‹ˆ๋‹ค.
๋”ฐ๋ผ์„œ O(w * 26 * 1^(w - 1)) = O(w)์ž…๋‹ˆ๋‹ค.

์ตœ์•…์˜ ๊ฒฝ์šฐ๋Š” dot์˜ ๊ฐœ์ˆ˜๊ฐ€ 2์ด๋ฉด์„œ 2๋ฒˆ ๋‹ค Branch๊ฐ€ 26๊ฐœ๋ผ๋ฉด ๋‹ค์Œ ์žฌ๊ท€ ํ˜ธ์ถœ์ด 26๋ฒˆ์ธ ๊ฒฝ์šฐ๊ฐ€ 2๋ฒˆ์”ฉ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ํ•˜์ง€๋งŒ ๊ทธ 2๋ฒˆ์„ ์ œ์™ธํ•˜๋ฉด ์—ฌ์ „ํžˆ 1๊ฐœ์˜ Branch์— ๋Œ€ํ•ด ๋งค๋ฒˆ ์žฌ๊ท€ ํ˜ธ์ถœ์ด 1๋ฒˆ๋งŒ ์ผ์–ด๋‚ฉ๋‹ˆ๋‹ค.
๊ทธ๋ž˜์„œ O(w * 26^2 * 1^(w - 2)) = O(w)์ž…๋‹ˆ๋‹ค.

๋‹ค์‹œ ๋งํ•ด O(26^w)์„ O(w * (1 + 26 + 26^2)) = O(w)์œผ๋กœ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ๋ฌธ์ œ์˜ ๋‹ค์Œ ์กฐ๊ฑด๊ณผ ๊ฒฐํ•ฉํ•˜๋ฉด w * (1 + 26 + 26^2) = 25 * (1 + 26 + 676) = 25 * 703 = 17575์ด๋ผ์„œ ๊ฝค ํฝ๋‹ˆ๋‹ค:

1 <= word.length <= 25

๊ฒฐ๋ก ์ ์œผ๋กœ ๋‹ค์Œ ์กฐ๊ฑด์— ๋”ฐ๋ผ ์ตœ๋Œ€ 17575 * 10^4๋ฒˆ์ด๋ผ ์•„์Šฌ์•„์Šฌํ•ฉ๋‹ˆ๋‹ค:

At most 10^4 calls will be made to addWord and search.

  1. ํ’€์ด 2: Trie 1

def addWord(self, word: str) -> None:
def dfs(node, idx):
if idx == len(word):
node["$"] = True
return
if "." not in node:
node["."] = {"$": False}
dfs(node["."], idx + 1)
ch = word[idx]
if ch not in node:
node[ch] = {"$": False}
dfs(node[ch], idx + 1)
dfs(self.root, 0)

๋‹จ์–ด๋ฅผ ์ถ”๊ฐ€ํ•  ๋•Œ, ์žฌ๊ท€ ํ•จ์ˆ˜ ๋‚ด์—์„œ 2๋ฒˆ์˜ ์—ฐ์‡„ ํ˜ธ์ถœ์ด ์ผ์–ด๋‚˜๋ฉฐ, ํ˜ธ์ถœ ํŠธ๋ฆฌ์˜ ๊นŠ์ด๋Š” ๊ธ€์ž์˜ ์ˆ˜์— ๋น„๋ก€ํ•ฉ๋‹ˆ๋‹ค.
๋”ฐ๋ผ์„œ `addWord()` ๋ฉ”์„œ๋“œ์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„์™€ ๊ณต๊ฐ„ ๋ณต์žก๋„๋Š” ๋ชจ๋‘ `O(2^w)`์ด ๋ฉ๋‹ˆ๋‹ค.

์ด๋ฒˆ์—๋Š” O(2^w)์˜ ์„ค๋ช…์œผ๋กœ ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค.
๊ทธ๋Ÿฐ๋ฐ ์•ž์„œ ์–ธ๊ธ‰ํ•œ ๋ฌธ์ œ์˜ ์กฐ๊ฑด์„ ํ™œ์šฉํ•˜๋ฉด ์•ฝ๊ฐ„์˜ ๋ณ€ํ˜•์œผ๋กœ ์ƒํ•œ์„ ๋” ์ค„์ธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

There will be at most 2 dots in word for search queries.

    def addWord(self, word: str) -> None:
        def dfs(node, idx, chance):
            if idx == len(word):
                node["$"] = True
                return

            if chance > 0:
                if "." not in node:
                    node["."] = {"$": False}
                dfs(node["."], idx + 1, chance - 1)

            ch = word[idx]
            if ch not in node:
                node[ch] = {"$": False}
            dfs(node[ch], idx + 1, chance)

        dfs(self.root, 0, 2)

์—ญ์‹œ ๊ฒฝ์šฐ๋ฅผ ๋‚˜๋ˆ„์–ด ์…€ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
dot์˜ ๊ฐœ์ˆ˜๊ฐ€ 0์ธ ๋ฌธ์ž์—ด, 1์ธ ๋ฌธ์ž์—ด, 2์ธ ๋ฌธ์ž์—ด์ด ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.
dot์˜ ๊ฐœ์ˆ˜๊ฐ€ 0์ธ ๋ฌธ์ž์—ด์€ 1๊ฐœ, 1์ธ ๋ฌธ์ž์—ด์€ 26๊ฐœ, 2์ธ ๋ฌธ์ž์—ด์€ 26 choose 2 = 26 * 25 / 2 = 325๊ฐœ์ž…๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ๋ฌธ์ž์—ด๋งˆ๋‹ค ์ตœ์•…์˜ ๊ฒฝ์šฐ ๋งค๋ฒˆ ์ƒˆ๋กœ์šด w๊ฐœ์˜ ๋…ธ๋“œ๋ฅผ ์ค‘๋ณต ์—†์ด ์ฒ˜์Œ์œผ๋กœ ๋ฐฉ๋ฌธํ•˜๊ฑฐ๋‚˜ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์‹œ ๋งํ•ด O(2^w)๋ฅผ O(w * sum(k in [0, 2], 26 choose k)) = O(w * (1 + 26 + 325)) = O(352w) = O(w)์œผ๋กœ ๋‚ฎ์ถœ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ด๋ฒˆ์—๋Š” ์ด์ „ O(w) ํ’€์ด๋ณด๋‹ค w๋ฐฐ ๋” ํฌ๊ฒŒ ๊ณ„์‚ฐ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฌธ์ œ์˜ ๋‹ค์Œ ์กฐ๊ฑด๊ณผ ๊ฒฐํ•ฉํ•˜๋ฉด ์—ฌ์œ  ์—†์ด ์ดˆ๊ณผํ•˜๋Š” ์ด์œ ๋ฅผ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

1 <= word.length <= 25

๊ทธ๋ž˜์„œ ์ตœ์•…์˜ ๊ฒฝ์šฐ 352w = 352 * 25 = 8800์ด๋ผ 8800 * 10^4 = 88 * 10^6๋ฒˆ์ด๋ฉด ์‹œ๊ฐ„์€ ๋‚˜์˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค:

At most 10^4 calls will be made to addWord and search.

๊ทธ๋Ÿฌ๋‚˜ ๊ณต๊ฐ„์€ ์ ์–ด๋„ 4๋ฐ”์ดํŠธ์”ฉ ๊ณ„์‚ฐํ•˜๋”๋ผ๋„ 4 * 88 * 10^6 B = 352 MB์ด๋ฏ€๋กœ ์ด ์ฝ”๋“œ๋„ ๋ฉ”๋ชจ๋ฆฌ ์ดˆ๊ณผ๋ฅผ ํ•ด๊ฒฐํ•˜์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค.

ํ•œํŽธ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ฌธ์ œ์—์„œ๋Š” ๊ณต๊ฐ„์ด ์‹œ๊ฐ„๋ณด๋‹ค 4๋ฐฐ ์ด์ƒ ๋น„์‹ผ ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋‹ค๋Š” ๊ตํ›ˆ์„ ์–ป์„ ์ˆ˜ ์žˆ๊ตฐ์š”!
1์ดˆ์˜ ์‹œ๊ฐ„์€ ํ—ˆ์šฉํ•˜๋ฉด์„œ๋„ ๋น„์Šทํ•œ ๋ณต์žก๋„์˜ ๊ณต๊ฐ„ 400MB ์ด์ƒ์€ ๋ถˆํ—ˆํ•œ๋‹ค๋ฉด์š”.

ํ˜น์‹œ ์ด ์ฝ”๋“œ์˜ ๋ณต์žก๋„ ์ƒํ•œ์„ ๋” ๋‚ฎ์ถฐ์„œ ๊ณ„์‚ฐํ•˜๊ฑฐ๋‚˜ ์ด๋ฅผ ์œ„ํ•ด ์ถ”๊ฐ€๋กœ ์ฝ”๋“œ๋ฅผ ๋ณ€ํ˜•ํ•  ์•„์ด๋””์–ด๊ฐ€ ์žˆ์œผ์‹  ๋ถ„๊ป˜์„œ๋Š” ๊ณต์œ ํ•ด ์ฃผ์‹œ๋ฉด ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions