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

최민길(Gale)·2023년 11월 15일
1

알고리즘

목록 보기
145/172

문제 링크 : https://www.acmicpc.net/problem/12015

이 문제는 이분 탐색을 이용하여 풀 수 있습니다.

가장 긴 증가하는 부분 수열을 구하는 방식은 다음과 같습니다.

  1. 수열 A를 탐색하면서 가장 긴 증가하는 부분 수열이 비었을 경우 수열 A 값을 추가
  2. 부분 수열이 비어있지 않은 경우 가장 밖에 있는(가장 큰) 수가 수열 A보다 작을 경우 A 값을 추가
  3. 가장 큰 수가 수열 A보다 클 경우 부분 수열 내의 수 중 수열 A보다 큰 수 중 가장 작은 수와 대치

이 때 3번의 경우 문제에서 구하고자 하는 것이 수열의 길이이기 때문에 대치하는 방식으로 진행하여도 길이 자체는 변화가 없으며, 뒤의 다른 큰 수가 왔을 때 추가 작업이 용이하기 때문에 대치로 진행합니다.

이 과정에서 부분 수열 내의 수 중 수열 A보다 큰 수 중 가장 작은 수의 탐색을 이분 탐색으로 진행합니다. 0과 수열의 최대 인덱스를 양 끝 범위로 하여 중간값 인덱스가 현재 값보다 크거나 같을 경우 현재 인덱스를 최댓값으로, 그렇지 않다면 최소 인덱스를 증가시키는 방식으로 구합니다.

다음은 코드입니다.

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

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

        List<Integer> res = new ArrayList<>();
        for(int i=0;i<N;i++){
            int val = A[i];
            if(res.isEmpty()) res.add(val);
            else{
                if(res.get(res.size()-1) < val) res.add(val);
                else{
                    int min = 0;
                    int max = res.size()-1;
                    while(min<max){
                        int mid = (min+max)/2;
                        if(res.get(mid)>=val) max=mid;
                        else min=mid+1;
                    }
                    res.set(max,val);
                }
            }
        }

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

profile
저는 상황에 맞는 최적의 솔루션을 깊고 정확한 개념의 이해를 통한 다양한 방식으로 해결해오면서 지난 3년 동안 신규 서비스를 20만 회원 서비스로 성장시킨 Software Developer 최민길입니다.

0개의 댓글

관련 채용 정보