[Java] 백준 12015 가장 긴 증가하는 부분 수열 2

hyunnzl·2025년 7월 4일

백준

목록 보기
94/116
post-thumbnail

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

난이도

골드 2

문제

수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오.

예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {10, 20, 10, 30, 20, 50} 이고, 길이는 4이다.

입력

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

출력

첫째 줄에 수열 A의 가장 긴 증가하는 부분 수열의 길이를 출력한다.

내 코드

import java.io.*;
import java.util.*;

class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int N = Integer.parseInt(br.readLine());
    
        int[] arr = new int[N];
        StringTokenizer st = new StringTokenizer(br.readLine());
        for(int i = 0; i < N; i++){
            arr[i] = Integer.parseInt(st.nextToken());
        }

        ArrayList<Integer> lis = new ArrayList<>();
        for(int num : arr){
            if(lis.isEmpty() || lis.get(lis.size() - 1) < num){
                lis.add(num);
            }else{
                int left = 0;
                int right = lis.size() - 1;
                while(left < right){
                    int mid = (left + right) / 2;
                    if(lis.get(mid) >= num){
                        right = mid;
                    }else{
                        left = mid + 1;
                    }
                }
                lis.set(right, num);
            }
        }

        System.out.println(lis.size());
    }
}


  1. 빈 리스트 LIS 준비

  2. 수열의 숫자들을 하나씩 보면서:

  • LIS가 비어있거나, 마지막 수 < 현재 수이면 → 그냥 뒤에 붙임 (길이 늘어남)
  • 현재 수 ≤ LIS의 어떤 값이면 → 그 중 제일 처음 큰 값 위치를 찾아서 바꿔치기 (lower_bound)

=> 결국 LIS에는 진짜 수열은 아니지만 LIS 길이를 구할 수 있는 최소 후보들만 남는다.


입력: 10 20 10 30 20 50
LIS 상태 변화:

[]10
[10]20
[10, 20]1010을 넣을 자리는 0 (바꿔치기)
[10, 20]30  → 끝에 붙임
[10, 20, 30]20 → 자리는 1 (바꿔치기)
[10, 20, 30]50 → 끝에 붙임

최종 LIS 후보: [10, 20, 30, 50] → 길이 = 4

0개의 댓글