JonghoonAn
어제보다 하나 더
JonghoonAn
전체 방문자
오늘
어제
  • 분류 전체보기
    • 알고리즘
    • 프로젝트
    • 배운점
    • ML
    • 학교 공부
      • OS
      • 네트워크
      • 시스템 프로그래밍
      • 데이터베이스
      • 소프트웨어 분석 및 설계

블로그 메뉴

  • 홈
  • 알고리즘
  • 배운점
  • 학교 공부
  • 머신러닝

공지사항

인기 글

태그

  • 가중치 초기화
  • 활성화 함수
  • 인공지능
  • 역전파
  • neural network
  • convolutional neural network
  • 인공신경망
  • ConvNets
  • 전이 학습
  • lecture6
  • Transfer learning
  • Backpropagation
  • convolutional layer
  • 인공 신경망
  • rnn
  • CNN Architecture
  • conv
  • 합성곱
  • recurrent network
  • CS231
  • lecture7
  • Learning rate
  • cs231n
  • activation function
  • convolutional network
  • 인공지능 학습
  • 학습률
  • lecture9
  • lecture10
  • pooling

최근 댓글

최근 글

티스토리

JonghoonAn

어제보다 하나 더

백준 14003 번 : 가장 긴 증가하는 부분 수열 5
알고리즘

백준 14003 번 : 가장 긴 증가하는 부분 수열 5

2021. 5. 19. 20:50

문제

문제 분석

증가 수열 문제 시리즈를 몇개 풀어봐서 얕봤었다.... 어려웠다. 다른 점이라곤 범위가 0에서 -10만정도로 바뀐 것이고 경로를 추가로 출력해야 했었다.

가장 먼저 생각난 것은 갯수를 구할때 쓰인 DP를 그대로 이용하는 것이었다. DP[i]는 길이가 i인 증가하는 수열에서 가장 작은 끝값을 저장하는 것이었는데 이 모양이 부분 증가수열이라서 그대로 이것을 출력했는데 틀렸었다.

당연한게 이것은 가장 긴 증가하는 부분 수열을 위해서 계속 갱신되기 때문이다. 예를 들어 456712이런 수열이 존재한다면 DP에는 4567이 아닌 1267이 존재할 것이고 이는 입력의 증가하는 부분 수열이 아니므로 틀리게 되는 것이다.

그래서 이 경로를 저장할 두번째 방식으로 생각해낸 것이 각 인덱스 별로 (부분수열별로) path를 갖고, 하나 추가되면 이전 경로를 복사하고,  새 값을 붙여서 i+1의 경로로 저장하고, 갱신된다면 i번째의 path에서 끝값을 바꾸는 방식으로 구현하고자 하였다.

하지만 n = 1,000,000이고 1 + 2 + 3...+n = n^2이므로 30여 퍼센트 이후로 메모리 초과가 났었다.

반드시 1차원 배열로 경로를 표현해야 한다는 것을 알고, 생각을 전환해야했다. i번째 입력을 처리할 때, j번째 위치에 값이 배정되었다면(즉, 갱신되거나 새로 추가되었다면) ARR[i] = j를 해주었다. 그리고 마지막에 N부터 1까지 내려가면서  최종 수열의 길이, len(path)부터 1까지 차례대로 가장 최근에 존재한 인덱스를 찾으면 된다. 왜냐하면 현재 찾고자 하는 것이 k번째 원소라고 할 때 가장 마지막에 나온 k값을 갖는 것이 path의 구성 원소이고 그 이전의 것은 모두 무시되어야 할 것들이기 때문이다. (그 사이에 나온 1~k-1은 갱신을 위해 사용된 것이므로, path에 속할 수 있는 k-1번째 원소는 반드시 k를 찾은 후에 나와야 한다. )

 

코드

#include<stdlib.h>
#include<iostream>
#include<string.h>
#include<string>
#include<vector>
#include<queue> // priority_queue 포함
#include<set>
#include<unordered_set>
#include<map>
#include<unordered_map>

#include<algorithm>
#include<math.h>
#include<climits> // 자료형 limit포함


using namespace std;

typedef long long int lld;
// 2차원 DP? : 10^6 -> 12ㄴㄴ
// 1+2+3....+10^6 -> 10^12 (대충), 1억 = 10^8 ㄴㄴ 
vector<int> DP;
vector<int> input_v;
int p[1000001] = {0};

int binary_search(int n)
{
    int hi = DP.size()-1;
    int low = 1;
    int mid = 0;
    while(hi > low)
    {
        mid = (hi+low)/2;
        if(n > DP[mid])
            low = mid+1;
        else if (n < DP[mid])
            hi = mid;
        else
            return mid;
    }
    // cout << low << " " << mid << " " << hi << endl;
    return hi;
}

void solution()
{
    // code
    int N;
    cin >> N;
    vector<int> tmp_v;
    for(int i=0; i<N; i++)
    {
        int tmp_int;
        cin >> tmp_int;
        input_v.push_back(tmp_int);
    }
    DP.push_back(-1000000001);
    for(int i=0; i<input_v.size(); i++)
    {
        if(DP[DP.size()-1] < input_v[i])
        {
            DP.push_back(input_v[i]);
            tmp_v.push_back(input_v[i]);
            p[i] = DP.size()-1;
        }
        else
        {
            int cmp_idx = binary_search(input_v[i]); 
            DP[cmp_idx] = input_v[i];
            p[i] = cmp_idx;
        }
    }
    vector<int> output;
    int now_val = DP.size()-1;
    for(int i = N-1; i>=0; i--)
    {
        if(p[i] == now_val)
        {
            output.push_back(input_v[i]);
            now_val--;
        }
        if(now_val == 0)
            break;
    }
    cout << DP.size()-1 << endl;
    for(int i=output.size()-1; i>=0; i--)
    {
        cout << output[i] << " ";
    }


}

int main ()
{
    iostream::sync_with_stdio(0); // 이제 C stdio의 입출력 사용 불가
    cin.tie(NULL);
    cout.tie(NULL); // 개행도 \n로 하도록 하자.
    solution();
    return 0;
}

개선점?

메모리와 실행 시간을 항상 염두해두자.

 

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

'알고리즘' 카테고리의 다른 글

백준 17370번 육각형 우리 속의 개미  (0) 2021.07.09
백준 10879번 Speak your mind!  (0) 2021.07.09
백준 1238 : 파티 / 플로이드 워셜 알고리즘  (0) 2021.05.19
백준 20543 번 : 폭탄 던지는 태영이 / 2D prefix-sum  (1) 2021.05.19
2020 카카오 인턴십 for Tech developers 코딩테스트 3번  (0) 2021.05.07
    '알고리즘' 카테고리의 다른 글
    • 백준 17370번 육각형 우리 속의 개미
    • 백준 10879번 Speak your mind!
    • 백준 1238 : 파티 / 플로이드 워셜 알고리즘
    • 백준 20543 번 : 폭탄 던지는 태영이 / 2D prefix-sum
    JonghoonAn
    JonghoonAn
    https://github.com/jjong0225 숭실대 소프트
    hELLO. 티스토리 스킨을 소개합니다.
    제일 위로

    티스토리툴바