๋ฌธ์ ๋งํฌ
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
์ด๋ ๊ฒ ์ฝ๋๋ฅผ ์์ฑํ์๋๋ฐ ๋จผ์ ๋ชจ๋ ํ์ด๋ฅผ ๊ตฌํด์ค๋ค๋ ๋ถ๋ถ์์ ์๊ฐ๋ณต์ก๋๊ฐ 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
๋ง์ง๋ง์ผ๋ก ๋ ๋ฌธ์์ด์ ๊ธธ์ด๊ฐ ๊ฐ์์ง ๊ณ์ฐํ๋ค.
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
- ์คํ ๊ฒฐ๊ณผ
์ฐธ๊ณ ๋ต์
"""
์คํ ์๊ฐ : 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
- ์คํ ๊ฒฐ๊ณผ