알고리즘/알고리즘 문제풀이

17298번: 오큰수 [C++]

mint* 2023. 2. 8. 23:55
728x90

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

 

17298번: 오큰수

첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000,000)이 주어진다. 둘째 줄에 수열 A의 원소 A1, A2, ..., AN (1 ≤ Ai ≤ 1,000,000)이 주어진다.

www.acmicpc.net

 

오큰수

시간 제한메모리 제한제출정답맞힌 사람정답 비율
1 초 512 MB 56506 19028 13655 32.679%

문제

크기가 N인 수열 A = A1, A2, ..., AN이 있다. 수열의 각 원소 Ai에 대해서 오큰수 NGE(i)를 구하려고 한다. Ai의 오큰수는 오른쪽에 있으면서 Ai보다 큰 수 중에서 가장 왼쪽에 있는 수를 의미한다. 그러한 수가 없는 경우에 오큰수는 -1이다.

예를 들어, A = [3, 5, 2, 7]인 경우 NGE(1) = 5, NGE(2) = 7, NGE(3) = 7, NGE(4) = -1이다. A = [9, 5, 4, 8]인 경우에는 NGE(1) = -1, NGE(2) = 8, NGE(3) = 8, NGE(4) = -1이다.

입력

첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000,000)이 주어진다. 둘째 줄에 수열 A의 원소 A1, A2, ..., AN (1 ≤ Ai ≤ 1,000,000)이 주어진다.

출력

총 N개의 수 NGE(1), NGE(2), ..., NGE(N)을 공백으로 구분해 출력한다.

예제 입력 1 복사

4
3 5 2 7

예제 출력 1 복사

5 7 7 -1

예제 입력 2 복사

4
9 5 4 8

예제 출력 2 복사

-1 8 8 -1

 

흐름(선생님 설명 포함)

시간 초과된 코드

#include <bits/stdc++.h>
using namespace std;

int n, a[1000004], answer[1000004];
int main(){
    ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
    //1. 입력받기
    cin >> n;
    for(int i=1;i<=n;i++){
        cin >> a[i];
    }
    //2. 큰 수 나오면 break
    for(int i=1;i<=n-1;i++){
        for(int j=i+1;j<=n;j++){
            if(a[i]<a[j]) {
                answer[i]= a[j];
                break;
            }
            answer[i]=-1;
        }
    }
    answer[n]=-1; //마지막 원소는 -1
    //3. 정답 출력
    for(int i=1;i<=n;i++) cout << answer[i] << " ";
    return 0;

}

 

100만을 제곱하면 1조이다... for문 두번말고 한번으로 가능한 알고리즘이 필요하다.

break을 사용하여 반복문에 가지치기를 했기때문에 시간초과가 안될거라고 예상했지만.. 시간초과 발생..

 

다른 자료구조를 이용해야한다..

 

선생님 코드

#include <bits/stdc++.h>
using namespace std;

int n,a[1000004], ret[1000004];
stack<int> s;

int main(){
    ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
    //1. 입력받기
    cin >> n;
    memset(ret, -1, sizeof(ret));

    //2. 스택 이용하여 오큰수 찾기
    for(int i=0;i<n;i++){
        cin >> a[i];
        while(s.size() && a[s.top()]<a[i]){
            ret[s.top()]=a[i]; s.pop();
        }
        s.push(i);
    }
    //3. 정답 출력하기
    for(int i=0;i<n;i++) cout << ret[i] << " ";
    return 0;
}

괄호 문제와 같은 방식의 문제이다.

짝짓기 문제는 스택을 사용한다!!

스택 원소를 인덱스로 저장하는 것은 순서대로 오큰수를 저장하기 위해서이다. 

728x90