์๋ ํ์ธ์, ์ฌ๋ฌ๋ถ! ์ค๋์ ์ต์ฅ ์ฆ๊ฐ ๋ถ๋ถ ์์ด(Longest Increasing Subsequence, LIS) ์๊ณ ๋ฆฌ์ฆ์ ์ด์ง ํ์์ ์ด์ฉํด ํจ์จ์ ์ผ๋ก ํธ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์๋ณด๊ฒ ์ต๋๋ค. ๐ง โจ ์ด๋ณด์๋ ์ฝ๊ฒ ๋ฐ๋ผ์ฌ ์ ์๋๋ก ํ๋ํ๋ ๋จ๊ณ๋ณ๋ก ์ค๋ช ๋๋ฆด ํ ๋ ๋๊น์ง ํจ๊ป ํด์ฃผ์ธ์!
์ต์ฅ ์ฆ๊ฐ ๋ถ๋ถ ์์ด(LIS)์ ์ฃผ์ด์ง ์์ด์์ ์ฆ๊ฐํ๋ ๋ถ๋ถ ์์ด ์ค ๊ฐ์ฅ ๊ธด ๊ฒ์ ์ฐพ๋ ๋ฌธ์ ์
๋๋ค. ์๋ฅผ ๋ค์ด, ์์ด [10, 20, 10, 30, 20, 50]
์ LIS๋ [10, 20, 30, 50]
์ผ๋ก ๊ธธ์ด๋ 4
์
๋๋ค.
์ด์ง ํ์์ ํ์ฉํ๋ฉด LIS ์๊ณ ๋ฆฌ์ฆ์ ์๊ฐ ๋ณต์ก๋๋ฅผ O(n log n)์ผ๋ก ์ค์ผ ์ ์์ต๋๋ค. ์ด๋ป๊ฒ ๊ฐ๋ฅํ์ง ํจ๊ป ์์๋ณผ๊น์?
tails
๋ฐฐ์ด ์์ฑ: ํ์ฌ๊น์ง ๊ฐ๋ฅํ LIS์ ๋ง์ง๋ง ์์๋ค์ ๊ด๋ฆฌํฉ๋๋ค.tails_idx
๋ฐฐ์ด ์์ฑ: tails
์ ์ ์ฅ๋ ์์๋ค์ด ์๋ ์์ด์์ ์ด๋์ ์์นํ๋์ง ๊ธฐ๋กํฉ๋๋ค.prev_idx
๋ฐฐ์ด ์์ฑ: ๊ฐ ์์์ ์ด์ ์์์ ์ธ๋ฑ์ค๋ฅผ ์ ์ฅํ์ฌ, ์ต์ข
์ ์ผ๋ก ์์ด์ ์ญ์ถ์ ํ ์ ์๊ฒ ํฉ๋๋ค.import bisect
def lis(sequence):
n = len(sequence)
tails = []
tails_idx = []
prev_idx = [-1] * n
์์ด์ ๊ฐ ์์ num
๊ณผ ๊ทธ ์ธ๋ฑ์ค i
์ ๋ํด ๋ค์์ ์ํํฉ๋๋ค:
pos = bisect.bisect_left(tails, num)
tails
์
๋ฐ์ดํธ:pos
๊ฐ tails
์ ๊ธธ์ด์ ๊ฐ์ผ๋ฉด num
์ tails
์ ์ถ๊ฐtails[pos]
๋ฅผ num
์ผ๋ก ๋์ฒดtails_idx[pos]
๋ฅผ ํ์ฌ ์ธ๋ฑ์ค i
๋ก ์
๋ฐ์ดํธprev_idx[i]
๋ pos > 0
์ผ ๋ tails_idx[pos - 1]
๋ก ์ค์ for i in range(n):
num = sequence[i]
pos = bisect.bisect_left(tails, num)
if pos == len(tails):
tails.append(num)
tails_idx.append(i)
else:
tails[pos] = num
tails_idx[pos] = i
if pos > 0:
prev_idx[i] = tails_idx[pos - 1]
tails_idx
์ ๋ง์ง๋ง ์ธ๋ฑ์ค๋ถํฐ ์์ํ์ฌ prev_idx
๋ฅผ ๋ฐ๋ผ๊ฐ๋ฉฐ LIS ์์ด์ ๋ณต์ํฉ๋๋ค.
lis_length = len(tails)
lis_sequence = []
k = tails_idx[-1] if tails_idx else -1
while k != -1:
lis_sequence.append(sequence[k])
k = prev_idx[k]
lis_sequence.reverse()
return lis_length, lis_sequence
import bisect
def lis(sequence):
n = len(sequence)
tails = []
tails_idx = []
prev_idx = [-1] * n
for i in range(n):
num = sequence[i]
pos = bisect.bisect_left(tails, num)
if pos == len(tails):
tails.append(num)
tails_idx.append(i)
else:
tails[pos] = num
tails_idx[pos] = i
if pos > 0:
prev_idx[i] = tails_idx[pos - 1]
lis_length = len(tails)
lis_sequence = []
k = tails_idx[-1] if tails_idx else -1
while k != -1:
lis_sequence.append(sequence[k])
k = prev_idx[k]
lis_sequence.reverse()
return lis_length, lis_sequence
# ๐ ์์ ์ฌ์ฉ
sequence = [10, 20, 10, 30, 20, 50]
length, subsequence = lis(sequence)
print("LIS์ ๊ธธ์ด:", length) # ์ถ๋ ฅ: 4
print("LIS ์์ด:", subsequence) # ์ถ๋ ฅ: [10, 20, 30, 50]
# ๐ ์ถ๊ฐ ์์
sequence2 = [3, 10, 2, 1, 20]
length2, subsequence2 = lis(sequence2)
print("LIS์ ๊ธธ์ด:", length2) # ์ถ๋ ฅ: 3
print("LIS ์์ด:", subsequence2) # ์ถ๋ ฅ: [3, 10, 20]
[10, 20, 10, 30, 20, 50]
tails: []
tails_idx: []
prev_idx: [-1, -1, -1, -1, -1, -1]
10 (i = 0
):
tails
: [10]
tails_idx
: [0]
prev_idx
: [-1, -1, -1, -1, -1, -1]
20 (i = 1
):
tails
: [10, 20]
tails_idx
: [0, 1]
prev_idx
: [-1, 0, -1, -1, -1, -1]
10 (i = 2
):
tails
: [10, 20]
tails_idx
: [2, 1]
prev_idx
: [-1, 0, -1, -1, -1, -1]
30 (i = 3
):
tails
: [10, 20, 30]
tails_idx
: [2, 1, 3]
prev_idx
: [-1, 0, -1, 1, -1, -1]
20 (i = 4
):
tails
: [10, 20, 30]
tails_idx
: [2, 4, 3]
prev_idx
: [-1, 0, -1, 1, 2, -1]
50 (i = 5
):
tails
: [10, 20, 30, 50]
tails_idx
: [2, 4, 3, 5]
prev_idx
: [-1, 0, -1, 1, 2, 3]
tails: [10, 20, 30, 50]
tails_idx: [2, 4, 3, 5]
prev_idx: [-1, 0, -1, 1, 2, 3]
4
[10, 20, 30, 50]
์ด์ง ํ์์ ํ์ฉํ LIS ์๊ณ ๋ฆฌ์ฆ์ ํจ์จ์ ์ด๊ณ ์ง๊ด์ ์
๋๋ค. tails
๋ฐฐ์ด์ ์ ์งํ๋ฉฐ ๊ฐ๋ฅํ ์์ ๊ฐ์ผ๋ก LIS๋ฅผ ํ์ฅํจ์ผ๋ก์จ ๋ ๊ธด LIS๋ฅผ ๊ตฌ์ฑํ ์ ์๋ ๊ธฐํ๋ฅผ ๊ทน๋ํํฉ๋๋ค. ๋ํ, tails_idx
์ prev_idx
๋ฅผ ํ์ฉํด ์ค์ LIS ์์ด์ ๋ณต์ํ ์ ์์ต๋๋ค.
์ด๋ฒ ํฌ์คํ ์ ํตํด O(n log n) ์๊ฐ ๋ณต์ก๋๋ก LIS๋ฅผ ๊ตฌํ๋ ๋ฐฉ๋ฒ์ ์ดํดํ์ จ๊ธธ ๋ฐ๋๋๋ค. ๐ช ๋ค์์๋ ์ ์ฉํ ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ๋ค์ ์ฐพ์๋ต๊ฒ ์ต๋๋ค. ๊ฐ์ฌํฉ๋๋ค! ๐