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

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

가장 긴 증가하는 부분 수열(LIS) 풀이 방법

부분 수열 : 임의의 수열이 주어질 때, 몇 개의 수를 제거하여 만든 수열
부분 수열 중 가장 긴 증가하는 부분 수열을 구하는 방법은 2가지가 있다.

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

2. Binary Search - 이분 탐색

1. 동적 계획법을 사용한 풀이 (백준 11053)

문제 : https://www.acmicpc.net/problem/11053

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)

print(max(dp))

dp: arr[i]를 마지막 원소로 가질 때 가장 긴 증가하는 부분 수열의 길이

현재 위치(i)의 원소 vs 이전에 있는 원소(j)

- 작다면 증가하는 부분 수열이 될 수 있기 때문에 dp값 설정

- dp값 : 현재 위치의 이전 숫자 중 최대 dp 값 + 1 (현재 값 추가하므로)

이렇게 dp를 통해 문제를 풀면 시간복잡도는 O(N^2)..

2. 이분 탐색을 사용한 풀이 (백준 12015)

해당 문제에서, n의 범위가 늘어났기 때문에 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()))
dp = [arr[0]]
for i in range(n):
    if arr[i] > dp[-1]:
        dp.append(arr[i])
    else:
        idx = bs(dp,arr[i])
        dp[idx] = arr[i]

print(len(dp))

dp : 가장 긴 증가하는 부분 수열을 저장하는 배열

현재 위치(i)의 원소 vs 이전 원소들

1. 현재 위치 원소가 더 크면 dp에 추가 (dp[-1]은 이전 원소들의 최댓값)

2. 더 작거나 같으면,, 이분 탐색을 통해 dp에 특정 값이 들어갈 위치를 찾고 arr[i]로 바꿔주기

3. dp의 길이 == 가장 긴 증가하는 부분 수열의 길이

cf) bisect 라이브러리를 사용해도 되지만, 나는 bisect 라이브러리 없이 구현하여 사용하였다.

이때 시간 복잡도는..? O(NlogN)이다

가장 긴 증가하는 부분 수열 자체를 구하는 방법은???

https://bskwak.tistory.com/260

 

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

가장 긴 증가하는 부분 수열의 '길이'을 구하는 방법은 1. DP(Dynamic Programming) - 동적 계획법 2. Binary Search - 이분 탐색 으로,, 이전 게시글 참고하기 : https://bskwak.tistory.com/259 이번 게시물은 '길이'가

bskwak.tistory.com

 

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

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

[DFS] 1967. 트리의 지름 (Python)  (0) 2024.03.08
[Python] 가장 긴 증가하는 부분 수열(LIS) 구하는 방법  (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) 구하는 방법
  • [코테 대비] 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)
  • 블로그 메뉴

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

    • 깃허브
  • 공지사항

  • 인기 글

  • 태그

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

  • 최근 글

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

티스토리툴바