[백준] 11054: 가장 긴 바이토닉 부분 수열 - Python

2023. 11. 25. 11:42·Algorithm (PS)
728x90

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

 

11054번: 가장 긴 바이토닉 부분 수열

첫째 줄에 수열 A의 크기 N이 주어지고, 둘째 줄에는 수열 A를 이루고 있는 Ai가 주어진다. (1 ≤ N ≤ 1,000, 1 ≤ Ai ≤ 1,000)

www.acmicpc.net

1. 알고리즘 유형 : DP 

증가하는 수열, 감소하는 수열 요런 유형은 DP 로 많이 접했어서 DP 라고 떠올렸다. 

정확하게는 DP 를 이용한 LIS (Longest Increasing Subsequence, 최장 증가 부분 수열)과 LDS (최장 감소 부분 수열) 을 활용하여 풀 수 있다. (상당히 문제가 naive하게 힌트를 주고 있다)

2. 풀이 

예전에 문제를 접한 적이 있어서 금방 떠올랐다. i번째 원소를 기준으로 증가하는 수열, 감소하는 수열 을 구한다음에 합치면 문제에서 원하는  S1< S2< ... Sk-1< Sk > Sk+1 > ... SN-1 > SN 를 만족하는 수열을 구할 수 있게 된다. 

증가하는 부분 수열과 감소하는 부분 수열을 각각 dp_up, dp_down 1차원 배열에 저장했다. 

여기서 dp_up[i] , dp_down[i] 의 의미는, i번째 원소를 포함했을 때 구할 수 있는 가장 긴 수열의 길이를 의미한다. 

문제에서의 예제로 풀어보면 다음과 같다. 

data = [1, 5, 2, 1, 4, 3, 4, 5, 2, 1]

 

i ) 증가하는 부분 수열의 경우 주어진 데이터 리스트를 왼쪽에서 오른쪽으로 선형탐색하여 구한다. 

dp_up[0] dp_up[1] dp_up[2] dp_up[3] dp_up[4] dp_up[5] dp_up[6] dp_up[7] dp_up[8] dp_up[9]
{1} {1, 5} {1, 2} {1} {1,2,4} {1, 2, 3} {1, 2, 3, 4} {1,2,3,4,5} {1, 2} {1}

ii ) 감소하는 부분 수열의 경우 주어진 데이터 리스트를 역방향 (오른쪽에서 왼쪽으로) 순회해서 구하면 된다. 즉, 오른쪽에서 왼쪽으로 진행하는 증가하는 부분 수열이라고 생각할 수 있다. 

dp_down[9] dp_down[8] dp_down[7] dp_down[6] dp_down[5] dp_down[4] dp_down[3] dp_down[2] dp_down[1] dp_down[0]
{1} {1, 2} {1, 2, 5} {1, 2, 4} {1, 2, 3} {1, 2, 3, 4} {1} {1, 2} {1,2,3,4,5} {1}
for i in range(N-1, -1, -1):
    for j in range(N-1, i, -1):
        if data[i] > data[j]:
            dp_down[i] = max(dp_down[i], dp_down[j]+1)

iii ) dp_up과 dp_down 의 결과를 합친다. 

마지막으로 구해놓은 dp_up 과 dp_down 을 합치는 부분에서 -1 을하는 이유는 

{1, 2, 3}, {3, 2, 1} 과 같은 예시에서 3이라는 원소가 겹치는데 한번만 카운트 해주어야 하기 때문이다. 

dp = [0] * N
for i in range(N):
    dp[i] = dp_up[i] + dp_down[i] -1 # 중복 원소 삭제

 

3. 전체 코드 

N = int(input())
data = list(map(int, input().split()))
# 1. 증가하는 부분 수열 구하기
dp_up = [1] * N

for i in range(N):
    for j in range(i):
        if data[i] > data[j]:
            dp_up[i] = max(dp_up[i], dp_up[j] + 1)
# 2. 감소하는 부분 수열 구하기
dp_down = [1] * (N+1)

for i in range(N-1, -1, -1):
    for j in range(N-1, i, -1):
        if data[i] > data[j]:
            dp_down[i] = max(dp_down[i], dp_down[j]+1)

# 3. 합쳐서 최대 길이 구하기
dp = [0] * N
for i in range(N):
    dp[i] = dp_up[i] + dp_down[i] -1 # 중복 원소 삭제
    
print(max(dp))
728x90

'Algorithm (PS)' 카테고리의 다른 글

[Code Snippet] 격자 안에서 밀고 당기기  (0) 2024.03.03
[프로그래머스] 순위 - Python  (0) 2024.01.28
[프로그래머스/kakao] 코딩 테스트 공부 (DP) - Python  (2) 2023.11.19
[프로그래머스] 미로 탈출 명령어 - Python (BFS)  (1) 2023.11.14
[LeetCode] 13. Roman to Integer - Python  (0) 2023.11.12
'Algorithm (PS)' 카테고리의 다른 글
  • [Code Snippet] 격자 안에서 밀고 당기기
  • [프로그래머스] 순위 - Python
  • [프로그래머스/kakao] 코딩 테스트 공부 (DP) - Python
  • [프로그래머스] 미로 탈출 명령어 - Python (BFS)
minjiwoo
minjiwoo
Data Engineering과 Cloud Native 기술에 대해 Dive Deep 하는 플랫폼 엔지니어가 되는 것을 목표로 하고 있습니다. 경험과 공부한 내용을 기록하며 지속가능한 엔지니어가 되는 것이 꿈입니다.
minjiwoo
minji's engineering note
minjiwoo
전체
오늘
어제
  • 분류 전체보기 (613)
    • Data Engineering (42)
      • Apache Spark (11)
      • Databricks & Delta Lake (9)
      • Airflow (3)
      • SQL (6)
      • Trouble Shooting (2)
      • Hadoop (2)
      • MLOps (1)
    • Cloud Engineering (104)
      • AWS (23)
      • Linux 🐧 (29)
      • Docker 🐳 (21)
      • Kubernetes ⚙️ (20)
      • Ansible (10)
    • Computer Science (87)
      • 네트워크 (9)
      • 운영체제 (25)
      • 정보처리기사 (48)
      • CS 기술 면접 스터디 (3)
    • Programming Languages (27)
      • Python (17)
      • C와 C++ (10)
    • Backend (5)
      • Django (2)
    • 프로젝트 (2)
      • 테크포임팩트 (2)
    • iOS (11)
      • 레이블러리 (2)
    • Algorithm (PS) (275)
      • LeetCode (6)
    • 개발일기 (30)
      • 내돈내산 후기🎮 (3)
      • 개발자 취준생 (5)
      • Today I Learned (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

  • Hi there

인기 글

태그

  • ansible
  • 데이터엔지니어링
  • AWS
  • 데이터브릭스
  • 백준
  • Databricks
  • 프로그래머스
  • 알고리즘
  • 파이썬
  • 스파크
  • Kubernetes
  • linux
  • EC2
  • 쿠버네티스
  • BFS
  • 코딩테스트
  • 운영체제
  • python
  • 카카오코딩테스트
  • Swift
  • dp
  • Leetcode
  • 백트래킹
  • 데이터엔지니어
  • 리눅스
  • SPARK
  • dfs
  • 빅데이터
  • 클라우드
  • docker

최근 댓글

최근 글

hELLO· Designed By정상우.v4.5.2
minjiwoo
[백준] 11054: 가장 긴 바이토닉 부분 수열 - Python
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.