๏นฅ

Leetcode 2531. Make Number of Distinct Characters Equal (Python3)

@๋‚จ์ œ์ด ยท 2024๋…„ 07์›” 26์ผ ยท 4๋ถ„
problem_solvingleetcodepython

๋ฌธ์ œ ๋งํฌ

https://leetcode.com/problems/make-number-of-distinct-characters-equal/


๋ฌธ์ œ ์š”์•ฝ

๋ฌธ์ž์—ด word1 ์™€ word2 ๊ฐ€ ์ฃผ์–ด์ง„๋‹ค. word1 ์˜ ์ธ๋ฑ์Šค i ์˜ ๊ฐ’๊ณผ word2 ์˜ ์ธ๋ฑ์Šค j ์˜ ๊ฐ’์„ ๊ฐ€์ ธ์™€ ์Šค์™‘์„ ํ•˜๊ฒŒ ๋œ๋‹ค. (word1[i] <-> word2[j])
์ด ๋•Œ, ๋‹จ ํ•œ ๋ฒˆ๋งŒ ์Šค์™‘์„ ํ•˜๊ฒŒ ๋  ๊ฒฝ์šฐ word1 ๊ณผ word2 ์˜ ๊ณ ์œ  ๋ฌธ์ž์˜ ๊ฐœ์ˆ˜๊ฐ€ ๊ฐ™์•„์งˆ ์ˆ˜ ์žˆ๋Š”๊ฐ€์— ๋Œ€ํ•ด์„œ ํŒ๋ณ„ํ•˜๋Š” ๋ฌธ์ œ๋‹ค.

์‰ฝ๊ฒŒ ๋งํ•ด์„œ word1 ์—์„œ ๋ฌธ์ž ํ•œ ๊ฐœ์™€ word2 ์—์„œ ๋ฌธ์ž ํ•œ ๊ฐœ๋ฅผ ๊ฐ€์ ธ์™€์„œ ์„œ๋กœ ๋ฐ”๊พธ์—ˆ์„ ๋•Œ ์ค‘๋ณต์„ ์ œ์™ธํ•œ ๋‚˜๋จธ์ง€ ๋ฌธ์ž์˜ ๊ฐœ์ˆ˜๊ฐ€ ๊ฐ™์€์ง€ ํ™•์ธํ•˜๋ฉด ๋˜๋Š” ๋ฌธ์ œ๋‹ค.

๋งŒ์•ฝ, ๊ณ ์œ ํ•œ ๋ฌธ์ž์˜ ๊ฐฏ์ˆ˜๊ฐ€ ๊ฐ™๋‹ค๋ฉด True, ๋‹ค๋ฅด๋‹ค๋ฉด False ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด ๋œ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, word1 = "abcc" ์™€ word2 = "aab" ๋ผ๋Š” ๋ฌธ์ž์—ด์ด ์ฃผ์–ด์งˆ ๋•Œ ๊ฐ ๋ฌธ์ž์—ด์—์„œ ๋ฌธ์ž ํ•˜๋‚˜์”ฉ ๊ฐ€์ ธ์™€ ์Šค์™‘์„ ํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฝ์šฐ๊ฐ€ ์„ฑ๋ฆฝํ•˜๊ฒŒ ๋œ๋‹ค.

word1 ์˜ ๋ฌธ์ž์—ด "abcc" ์—์„œ "c" ๋ฌธ์ž์™€ word2 ์˜ ๋ฌธ์ž์—ด "aab" ์—์„œ "a" ๋ฌธ์ž๋ฅผ ์Šค์™‘ํ•˜๊ฒŒ ๋˜๋ฉด word1 ์€ "abac" ๊ฐ€ ๋˜๊ณ  word2 ๋Š” "cab" ๊ฐ€ ๋œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๊ณ ์œ  ๋ฌธ์ž์˜ ์ˆ˜๋ฅผ ๋”ฐ์ ธ๋ณด๋ฉด word1 ์€ "a", "b", "c" ์˜ ๋ฌธ์ž๋กœ 3๊ฐœ ๊ฐ€ ๋˜๊ณ , word2 ๋Š” "a", "b", "c" ๋กœ word1 ๊ณผ ๊ฐ™์ด ๋ฌธ์ž 3๊ฐœ ๊ฐ€ ๋œ๋‹ค.

๋”ฐ๋ผ์„œ, ์ด๋Ÿฐ ๊ฒฝ์šฐ ๊ณ ์œ ํ•œ ๋ฌธ์ž์˜ ๊ฐฏ์ˆ˜๊ฐ€ ๋™์ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— True ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ฒŒ ๋œ๋‹ค.


๋ฌธ์ œ ํ’€์ด

์ด ๋ฌธ์ œ๋Š” ์‹œ์ž‘๋ถ€ํ„ฐ ์–ด๋–ป๊ฒŒ ํ’€์–ด์•ผํ• ์ง€ ๋˜๊ฒŒ ๋ง‰๋ง‰ํ–ˆ๋˜ ๊ฒƒ ๊ฐ™๋‹ค. ๋ฌธ์ž๋ฅผ ์Šค์™‘ํ•˜๋Š” ๋ถ€๋ถ„์„ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ•ด์ค„ ์ˆ˜ ์žˆ์„๊นŒ? ์— ๋Œ€ํ•œ ๊ณ ๋ฏผ์„ ๋งŽ์ด ํ–ˆ๋˜ ๊ฒƒ ๊ฐ™๋‹ค. ๊ทธ๋ž˜์„œ ๋– ์˜ค๋ฅธ ๋ฐฉ๋ฒ•์ด ์Šค์™‘ํ•  ๋ฌธ์ž์˜ ์ง์„ ๋งŒ๋“ค์–ด์„œ ํ•˜๋‚˜์”ฉ ๋‹ค ๋ฐ”๊ฟ”์ฃผ์ž๊ณ  ์ƒ๊ฐํ–ˆ๊ณ  ๋ชจ๋“  ์Šค์™‘์ด ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ๋ฅผ ๊ตฌํ•ด์„œ ๊ณ ์œ ํ•œ ๋ฌธ์ž์˜ ์ˆ˜๋ฅผ ๋น„๊ตํ•ด์ฃผ์—ˆ๋‹ค.

ํ•˜์ง€๋งŒ ์˜ˆ์™ธ ์ผ€์ด์Šค๋“ค์ด ๋‚˜์˜ค๊ฒŒ ๋˜๋ฉด์„œ ํ•˜๋‚˜์”ฉ ํ’€์–ด๊ฐ€์•ผํ–ˆ๊ณ  ๊ทธ ๊ฒฐ๊ณผ ํ’€์—ˆ์ง€๋งŒ ์‹œ๊ฐ„์ด 6146 ms ... ๊ฑฐ์˜ ๊ผด๋“ฑ์ด์—ˆ๋‹ค.

๊ทธ๋ž˜์„œ ํ•˜๋‚˜์˜ ์˜ˆ์ œ๋ฅผ ํ†ตํ•ด ๋‚ด๊ฐ€ ํ‘ผ ๋ฐฉ๋ฒ•๊ณผ ์ตœ์ ํ™”๋ฅผ ํ†ตํ•ด ์ตœ์ ์œผ๋กœ ํ‘ผ ๋ฐฉ๋ฒ•์„ ๋น„๊ตํ•ด๋ดค๋‹ค.

  • ์˜ˆ์ œ
Input: word1 = "abcc", word2 = "aab"
Output: true

๋‚ด๊ฐ€ ํ‘ผ ๋ฐฉ๋ฒ•

๋‚˜๋Š” ๋จผ์ € word1, word2 ๋ฅผ set() ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ๊ณ ์œ ํ•œ ๋ฌธ์ž๋ฅผ ๊ตฌํ•ด์ฃผ์—ˆ๋‹ค.

# dw is distinct word
dw1 = set(word1)
dw2 = set(word2)



๊ทธ๋ฆฌ๊ณ  ๊ณ ์œ ํ•œ ๋ฌธ์ž์˜ ๊ฐœ์ˆ˜๊ฐ€ ๋˜‘๊ฐ™๊ณ  ๊ณ ์œ ํ•œ ๋ฌธ์ž๊ฐ€ ๊ฐ™๋‹ค๋ฉด ์Šค์™‘์„ ํ•ด๋„ ๋˜‘๊ฐ™๊ธฐ ๋•Œ๋ฌธ์— True ๋ฅผ ๋ฐ˜ํ™˜ํ•ด์ฃผ์—ˆ๋‹ค.

if len(dw1) == len(dw2):
    if dw1 == dw2:
        return True

๋‹ค์Œ์œผ๋กœ ๋‘๊ฐœ์˜ ๊ณ ์œ ํ•œ ๋ฌธ์ž๋ฅผ ํ•ฉ์ณ์„œ ์Šค์™‘ํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ๊ฒฝ์šฐ๋ฅผ ๊ตฌํ•ด์ฃผ์—ˆ๋‹ค.

union_dw = dw1 | dw2

fair = []

for i in union_dw:
    for j in union_dw:
        fair.append([i, j])



๋งˆ์ง€๋ง‰์œผ๋กœ ๋ชจ๋“  ๊ฒฝ์šฐ์˜ ์ˆ˜๋ฅผ ๋‹ค ๊ณ„์‚ฐํ•ด์ค€๋‹ค.
์›๋ž˜์˜ ๋ฌธ์ž์—ด์„ ๋ณต์‚ฌํ•ด ๋ฆฌ์ŠคํŠธ๋กœ ๋งŒ๋“ค์–ด์ฃผ๊ณ  remove() ํ•จ์ˆ˜์™€ append() ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์Šค์™‘ํ•  ๋ฌธ์ž๋ฅผ ๋”ํ•˜๊ณ  ๋นผ์ค€๋‹ค.
๊ทธ๋ฆฌ๊ณ  set ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ๊ณ ์œ  ๋ฌธ์ž์˜ ์ˆ˜๋ฅผ ๋น„๊ตํ•œ๋‹ค.

๊ทธ๋ ‡๊ฒŒ ๊ฐœ์ˆ˜๊ฐ€ ๊ฐ™์œผ๋ฉด True ๊ฐ™์€ ๊ฒฝ์šฐ๊ฐ€ ์—†๋‹ค๋ฉด False ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ฒŒ ๋œ๋‹ค.

for a, b in fair:
    tdw1 = list(word1)
    tdw2 = list(word2)

    if a not in tdw1 or b not in tdw2:
        continue

    tdw1.append(b)
    tdw1.remove(a)
    
    tdw2.append(a)
    tdw2.remove(b)

    if len(set(tdw1)) == len(set(tdw2)):
        return True

return False

image3


์ด๋ ‡๊ฒŒ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์˜€๋Š”๋ฐ ๋จผ์ € ๋ชจ๋“  ํŽ˜์–ด๋ฅผ ๊ตฌํ•ด์ค€๋‹ค๋Š” ๋ถ€๋ถ„์—์„œ ์‹œ๊ฐ„๋ณต์žก๋„๊ฐ€ O((m+n)^2) ์œผ๋กœ ์‹œ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ฆด ๊ฒƒ์ด๊ณ  ๋ฆฌ์ŠคํŠธ์— ์Šค์™‘ํ•  ๋ฌธ์ž๋ฅผ ๋„ฃ๊ณ  ๋นผ๊ณ  ๋น„๊ตํ•˜๋Š” ๊ณผ์ •์—์„œ๋„ ์‹œ๊ฐ„ ๋ณต์žก๋„๊ฐ€ O((m+n)^3) ์œผ๋กœ ๋งŽ์€ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฌ๊ฒŒ ๋œ๋‹ค.

๋‹คํ–‰ํžˆ๋„ ์ปคํŠธ๋ผ์ธ ๋์— ๊ฑธ๋ ค ๋ฌธ์ œ๋ฅผ ํ’€ ์ˆ˜ ์žˆ์—ˆ์ง€๋งŒ ์–ด๋–ป๊ฒŒ ํ•˜๋ฉด ๋” ๊ฐ„๋‹จํ•˜๊ฒŒ ํ’€ ์ˆ˜ ์žˆ๊ณ  ์ตœ์ ํ™”์‹œํ‚ฌ ์ˆ˜ ์žˆ์„๊นŒ ๊ณ ๋ฏผํ•˜๋‹ค๊ฐ€ ๊ฒฐ๊ตญ ๋‹ค๋ฅธ ์‚ฌ๋žŒ์˜ ํ’€์ด๋ฅผ ๋ณด๊ฒŒ ๋˜์—ˆ๋Š”๋ฐ... ์ „ํ˜€ ์ƒ๊ฐ์ง€๋ชปํ•œ ๋ฐฉ๋ฒ•์ด๊ธฐ๋„ ํ–ˆ๊ณ  ๋„ˆ๋ฌด ๊ฐ„๋‹จํ•ด์„œ ๋‚ด๊ฐ€ ๋„ˆ๋ฌด ๋ณต์žกํ•˜๊ฒŒ ์ƒ๊ฐํ•œ๊ฑด๊ฐ€ ์‹ถ์—ˆ๋‹ค.


๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ํ‘ผ ๋ฐฉ๋ฒ•

๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ํ‘ผ ๋ฐฉ๋ฒ•์€ ์•„๋ž˜์™€ ๊ฐ™์•˜๋‹ค.

๋จผ์ €, ๋ฌธ์ž์—ด์˜ Counter() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ฌธ์ž์—ด ๋‚ด์˜ ๋ฌธ์ž์˜ ๊ฐœ์ˆ˜๋ฅผ ๊ตฌํ•ด์ค€๋‹ค.

Counter() ํ•จ์ˆ˜๋ฅผ ๋ชจ๋ฅด๋Š” ๊ฒƒ๋„ ์•„๋‹Œ๋ฐ ์™œ ์ƒ๊ฐ์„ ๋ชปํ–ˆ์„๊นŒ...
Counter() ํ•จ์ˆ˜๋ฅผ ๋ณด์ž๋งˆ์ž ๊ตณ์ด ์ง์ ‘ ์Šค์™‘ํ•ด์ค„ ํ•„์š” ์—†์ด ํ•˜๋‚˜ ๋นผ๊ณ  ๋”ํ•˜๊ณ ๋งŒ ํ•ด๋„ ๋˜๋Š”๊ตฌ๋‚˜ ํ•˜๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค.

w1_counter = Counter(word1)
w2_counter = Counter(word2)
  • ์ถœ๋ ฅ ๊ฒฐ๊ณผ
Counter({'c': 2, 'a': 1, 'b': 1})
Counter({'a': 2, 'b': 1})

๊ทธ๋Ÿผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด dictionary ๋กœ ์นด์šดํŒ…๋˜์–ด ์ถœ๋ ฅ๋œ๋‹ค.


์ด์ œ ์ด ๋ฌธ์ž๋ฅผ ํ•˜๋‚˜์”ฉ ๊ฐ€์ ธ์™€์„œ ๋ชจ๋“  ๊ฒฝ์šฐ์— ๋Œ€ํ•ด์„œ ์Šค์™‘์„ ์ง„ํ–‰ํ•ด์ฃผ๋ฉด ๋˜๋Š”๋ฐ ์Šค์™‘์ด ๋˜์—ˆ์„ ๊ฒฝ์šฐ๋ฅผ ๊ฐ€์ •ํ•˜๊ณ  ๋ฌธ์ž์˜ ๊ฐœ์ˆ˜๋ฅผ ์„ธ์–ด์ฃผ์—ˆ๋‹ค.

๋จผ์ € ๊ฐ ๋ฌธ์ž์—ด์—์„œ ๋‹จ์–ด์™€ ๊ฐœ์ˆ˜๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.

for c1, v1 in w1_counter.items():
    for c2, v2 in w2_counter.items():
        ...

๊ทธ๋ฆฌ๊ณ  ๋จผ์ € ํ˜„์žฌ ๋‘ ๋ฌธ์ž์˜ ๊ธธ์ด๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.

w1_len = len(w1_counter)
w2_len = len(w2_counter)

๋‹ค์Œ์œผ๋กœ ์ฒซ ๋ฒˆ์งธ ๋ฌธ์ž์—ด ๋จผ์ € ์Šค์™‘๋˜๋Š” ๊ฒฝ์šฐ๋ฅผ ๊ณ„์‚ฐํ•œ ๋‹ค์Œ ๋‘ ๋ฒˆ์งธ ๋ฌธ์ž์—ด๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์Šค์™‘๋˜๋Š” ๊ฒฝ์šฐ๋ฅผ ๊ณ„์‚ฐํ•ด์ค€๋‹ค.

# --- word1 ์Šค์™‘ ---

# ๋ฌธ์ž๊ฐ€ ํ•˜๋‚˜๋งŒ ์žˆ์„ ๊ฒฝ์šฐ
if v1 == 1:
    w1_len -= 1

# ๋ฌธ์ž๊ฐ€ ์—†๊ฑฐ๋‚˜ ์ด๋ฏธ ์žˆ๋Š” ๊ฒฝ์šฐ
if c2 not in w1_counter or (v1 == 1 and c1 == c2):
    w1_len += 1

# --- word2 ์Šค์™‘ ---

# ๋ฌธ์ž๊ฐ€ ํ•˜๋‚˜๋งŒ ์žˆ์„ ๊ฒฝ์šฐ
if v2 == 1:
    w2_len -= 1

# ๋ฌธ์ž๊ฐ€ ์—†๊ฑฐ๋‚˜ ์ด๋ฏธ ์žˆ๋Š” ๊ฒฝ์šฐ
if c1 not in w2_counter or (v2 == 1 and c1 == c2):
    w2_len += 1

image6


๋งˆ์ง€๋ง‰์œผ๋กœ ๋‘ ๋ฌธ์ž์—ด์˜ ๊ธธ์ด๊ฐ€ ๊ฐ™์€์ง€ ๊ณ„์‚ฐํ•œ๋‹ค.

if w1_len == w2_len:
    return True

์ •๋ฆฌํ•ด๋ณด์ž๋ฉด, ๋‚˜๋Š” ์ง์ ‘ ์Šค์™‘๋˜๋Š” ๊ณผ์ •์„ ๋ฆฌ์ŠคํŠธ๋กœ ๊ตฌํ˜„์„ ํ–ˆ์ง€๋งŒ ์ด ๋ฐฉ๋ฒ•์—์„œ๋Š” ๊ฐœ์ˆ˜๋ฅผ ํ†ตํ•ด ๋”ํ•ด์ฃผ๊ณ  ๋นผ์ฃผ๊ณ  ํ•˜๋ฉด์„œ ๋ฌธ์ž์—ด์ด ์Šค์™‘๋˜๋Š” ๊ณผ์ •์„ ๊ณ„์‚ฐํ–ˆ๋‹ค.

๋‹ค๋ฅธ ์‚ฌ๋žŒ์˜ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด์„œ ๋Š๋‚€ ์ ์€ ๋„ˆ๋ฌด ๋ณต์žกํ•˜๊ฒŒ ์ƒ๊ฐํ•˜๊ณ  ๋ฌธ์ œ๋ฅผ ํ’€์—ˆ๋˜ ๊ฒƒ ๊ฐ™๊ณ  ์กฐ๊ธˆ ๋” ๋‹จ์ˆœํ•˜๊ฒŒ ํ’€ ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ๋” ๋งŽ์ด ๊ณ ๋ฏผํ•˜๊ณ  ์‹œ๋„ํ•ด ๋ด์•ผ๊ฒ ๋‹ค.


์ œ์ถœ ๋‹ต์•ˆ

์ฒ˜์Œ ์ œ์ถœํ•œ ๋‹ต์•ˆ

"""
์‹คํ–‰ ์‹œ๊ฐ„ : 6146 ms
๋ฉ”๋ชจ๋ฆฌ ํฌ๊ธฐ : 20.80 MB
์‹œ๊ฐ„ ๋ณต์žก๋„ : O(word1.length * word2.length) == O(N^2)
"""
class Solution:
    def isItPossible(self, word1: str, word2: str) -> bool:
        # dw is distinct word
        dw1 = set(word1)
        dw2 = set(word2)

        if len(dw1) == len(dw2):
            if dw1 == dw2:
                return True

        union_dw = dw1 | dw2

        fair = []

        for i in union_dw:
            for j in union_dw:
                fair.append([i, j])

        for a, b in fair:
            tdw1 = list(word1)
            tdw2 = list(word2)

            if a not in tdw1 or b not in tdw2:
                continue

            tdw1.append(b)
            tdw1.remove(a)
            
            tdw2.append(a)
            tdw2.remove(b)

            if len(set(tdw1)) == len(set(tdw2)):
                return True

        return False
  • ์‹คํ–‰ ๊ฒฐ๊ณผ

image888


์ฐธ๊ณ  ๋‹ต์•ˆ

"""
์‹คํ–‰ ์‹œ๊ฐ„ : 106 ms
๋ฉ”๋ชจ๋ฆฌ ํฌ๊ธฐ : 17.62 MB
์‹œ๊ฐ„ ๋ณต์žก๋„ : O(word1.length * word2.length) == O(N^2)
"""

class Solution:
    def isItPossible(self, word1: str, word2: str) -> bool:
        w1_counter = Counter(word1)
        w2_counter = Counter(word2)

        for c1, v1 in w1_counter.items():
            for c2, v2 in w2_counter.items():
                w1_len = len(w1_counter)
                w2_len = len(w2_counter)
                
                # --- word1 ์Šค์™‘ ---

                # ๋ฌธ์ž๊ฐ€ ํ•˜๋‚˜๋งŒ ์žˆ์„ ๊ฒฝ์šฐ
                if v1 == 1:
                    w1_len -= 1
                
                # ๋ฌธ์ž๊ฐ€ ์—†๊ฑฐ๋‚˜ ์ด๋ฏธ ์žˆ๋Š” ๊ฒฝ์šฐ
                if c2 not in w1_counter or (v1 == 1 and c1 == c2):
                    w1_len += 1

                # --- word2 ์Šค์™‘ ---

                # ๋ฌธ์ž๊ฐ€ ํ•˜๋‚˜๋งŒ ์žˆ์„ ๊ฒฝ์šฐ
                if v2 == 1:
                    w2_len -= 1
                
                # ๋ฌธ์ž๊ฐ€ ์—†๊ฑฐ๋‚˜ ์ด๋ฏธ ์žˆ๋Š” ๊ฒฝ์šฐ
                if c1 not in w2_counter or (v2 == 1 and c1 == c2):
                    w2_len += 1

                if w1_len == w2_len:
                    return True
            
        return False
  • ์‹คํ–‰ ๊ฒฐ๊ณผ

image999