[Python] 가장 긴 증가하는 부분 수열(LIS) 구하는 방법

2024. 3. 4. 17:38·Computer Science/자료구조와 알고리즘

가장 긴 증가하는 부분 수열의 '길이'을 구하는 방법은

1. DP(Dynamic Programming) - 동적 계획법

2. Binary Search - 이분 탐색

으로,, 이전 게시글 참고하기 : https://bskwak.tistory.com/259 

 

이번 게시물은 '길이'가 아닌 가장 긴 증가하는 부분 수열(LIS) 자체를 구하는 방법이다.

풀이 방법을 간단하게 설명하면,

1. dp를 통해 LIS 길이 구하기

2. 역추적하여 배열 구하고 뒤집으면 구할 수 있음

 

관련 문제 : 

https://www.acmicpc.net/problem/14002

 

 

import sys
input = sys.stdin.readline

n = int(input())
arr = list(map(int, input().split()))

dp = [1 for i in range(n)]

for i in range(n):
    for j in range(i):
        if arr[i]>arr[j]:
            dp[i] = max(dp[i],dp[j]+1)
            
max_len = max(dp)
idx = dp.index(max_len)

res = []
while idx>=0:
    if dp[idx] == max_len:
        res.append(arr[idx])
        max_len -=1
    idx -=1

res.reverse()
print(*res)

 

max_len : 가장 긴 증가하는 부분 수열의 길이 

idx : max_len에 해당하는 위치 

res : 가장 긴 증가하는 부분 수열을 담을 배열

 

 arr = [10, 20, 10, 30, 20, 50] 일때, 

dp =[1, 2, 1, 3, 2, 4]

 

max_len = 4 이고, idx = 5 (초기값)

반복문을 하나씩 실행하면, 아래와 같이 추가된다. 즉, idx 4->3->2->1 에 해당하는 값을 추가하면 된다..

[50]
[50, 30]
[50, 30, 20]
[50, 30, 20, 10]

 

 

문제는,, 이렇게 풀면 14003 문제처럼 n의 범위가 커졌을 때, 시간 초과가 난다..

관련 문제 : https://www.acmicpc.net/problem/14003

 

위에서 dp 구하는 부분을 이분탐색을 통해 구하면 된다!

import sys
input = sys.stdin.readline

def bs(arr,target):
    left, right = 0, len(arr)-1
    while left<= right:
        mid = (left+right)//2
        if arr[mid]<target:
            left = mid+1
        else:
            right = mid-1
    return left

n = int(input())
arr = list(map(int, input().split()))
INF = int(1e10)

check = [0]*n
inc_arr = [INF]*n

for i, x in enumerate(arr):
    idx = bs(inc_arr,x)
    inc_arr[idx] = x
    check[i] = idx

max_len = max(check)
idx = check.index(max_len)

res = []
while idx>=0:
    if check[idx] == max_len:
        res.append(arr[idx])
        max_len -=1
        # print(res)
    idx -=1

res.reverse()
print(len(res))
print(*res)

 

 

저작자표시 비영리 변경금지 (새창열림)

'Computer Science > 자료구조와 알고리즘' 카테고리의 다른 글

[DFS] 1967. 트리의 지름 (Python)  (0) 2024.03.08
[Python]가장 긴 증가하는 부분 수열(LIS) 길이 구하는 방법 2가지  (0) 2024.03.04
[코테 대비] javascript 기본 문법  (0) 2024.02.20
[누적합] 10986. 나머지의 합 (Python)  (0) 2024.02.19
[LeetCode] 53. maximum subarray (Brute-Force와 카데인 알고리즘) (python 풀이)  (0) 2022.02.11
'Computer Science/자료구조와 알고리즘' 카테고리의 다른 글
  • [DFS] 1967. 트리의 지름 (Python)
  • [Python]가장 긴 증가하는 부분 수열(LIS) 길이 구하는 방법 2가지
  • [코테 대비] javascript 기본 문법
  • [누적합] 10986. 나머지의 합 (Python)
BS Kwak
BS Kwak
  • BS Kwak
    Slow but steady wins the race
    BS Kwak
  • 전체
    오늘
    어제
    • 카테고리 (161)
      • Project (2)
      • Next.js (3)
      • HTML+CSS+JS (17)
      • Computer Science (139)
        • Programming Language (52)
        • 자료구조와 알고리즘 (75)
        • Digital circuit (3)
        • 기타 error (9)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • 깃허브
  • 공지사항

  • 인기 글

  • 태그

    오블완
    c++error
    mysql error
    leetcode
    해시
    LNK2001
    cmd error
    런타임 에러
    티스토리챌린지
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.1
BS Kwak
[Python] 가장 긴 증가하는 부분 수열(LIS) 구하는 방법
상단으로

티스토리툴바