DP (1) 최장 증가 부분 수열
DP (1) 최장 증가 부분 수열 — #DP #다이나믹프로그래밍 #Dynamicprogramming #부분수열 #점화식 사용된 언어: 코틀린, 혹은 파이썬 순...
#백준#Naver Blog
#DP #다이나믹프로그래밍 #Dynamicprogramming #부분수열 #점화식
- 사용된 언어: 코틀린, 혹은 파이썬
- 순서: 로직, 코드 구현, 코드 분석
가장 긴 증가하는 부분 수열
Solved ac (class 4) 38.6%
최초 접근방법
⚠️ 처음에 문제를 잘못 읽어서 등차수열로 풀었음
👉 이후 수정하여 다음과 같은 코드로 작성
import sys
n = sys.stdin.readline()
A = list(map(int, sys.stdin.readline().rstrip().split(" ")))
# 정렬 쓰면 안된다.
seq_max_len = -1
for i in range(len(A)):
pivot = A[i]
tmp_len = 0
for j in range(i + 1, len(A)):
if A[j] > pivot:
tmp_len += 1
pivot = A[j]
seq_max_len = max(seq_max_len, tmp_len + 1)
print(seq_max_len)
- A\[j\]가 되는 순간 바로 Pivot을 변경한다.
- 이는 문제가 되는데 아래와 같은 경우가 발생할 수 있기 때문
10 20 30 22 23 24
✍️ 해당 코드를 적용하면
10 20 30 max = 3
🚀 실제 구현해야 하는 것
10 20 22 23 24 max = 5
- 문제 패턴을 생각해보면 j쪽에서 여러가지 경우의 수(마치 조합 처럼) 고려해야한다.
- DP 문제가 주로 이럼
DP
Dynamic programming을 응용하기가 어렵다. 문제를 보고 해당 문제가 DP인지 판단이 잘 안된다.
✍️ dp[i] = 끝이 A[i]인 최장 증가 부분 수열의 길이로 정의
1. dp[i] 정의에 의해서 A[i]의 이전의 값이 A[i] 보다 작은 경우에만 길이가 증가.
2. dp[i]는
dp[i - 1, i - 2 ...] 의 값이 dp[i] 보다 작고,
해당 idx의 A[i - 1, i - 2, ...] 는 A[i] 보다 작아야한다.
import sys
n = int(sys.stdin.readline())
A = list(map(int, sys.stdin.readline().rstrip().split(" ")))
# 정렬 쓰면 안된다.
seq_max_len = -1
dp = [1] * n
for i in range(1, len(A)):
num = A[i]
back = i - 1
max_dp_back = 0
while back >= 0:
if A[back] < num:
max_dp_back = max(dp[back], max_dp_back)
back -= 1
dp[i] = 1 + max_dp_back
print(max(dp))
- 정답이다.
- → 방향에서 중간에 ←으로 이동 하기 때문에 n(n - k)로 시간 복잡도는 O(n²)이 되겠다.
GPT에게 추천 받은 공부 방향
- DP 기본
- 1차원 배열 DP (최장 증가 부분 수열, 배낭문제)
- 점화식 세우는 연습하기
- Patience Sorting 기법
- LIS를 O(N logN)으로 푸는 방법