[백준] 17298번. 오큰수

leeeha·2022년 6월 25일
0

백준

목록 보기
31/186
post-thumbnail

문제

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

크기가 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)을 공백으로 구분해 출력한다.


풀이과정

시간 초과: O(n^2)

#include <iostream>
#include <vector>
using namespace std;

int main() {
	int n;
	cin >> n;

	vector<int> v;
	for(int i = 0; i < n; i++){
		int num;
		cin >> num;
		v.push_back(num);
	}

	vector<int> nge;

	for(int i = 0; i < n; i++){
		bool found = false;
		
		// i+1 인덱스부터 탐색 
		for(int j = i + 1; j < n; j++){
			// v[i]보다 크면서 인덱스가 가장 작은 수 저장  
			if(v[i] < v[j]){
				found = true;
				nge.push_back(v[j]);
				break;
			}
		}

		if(!found || i == n - 1){
			nge.push_back(-1);
		}
	}
	
	for(auto e: nge){
		cout << e << " ";
	}
	
	return 0;
}

🤔 다른 방법 생각해보기

https://cocoon1787.tistory.com/347

#include<iostream>
#include<algorithm>
#include<stack>
using namespace std;

stack<int> s;
int ans[100'0001];
int arr[100'0001];

int main(){
	int n;
	cin >> n;
	
	for (int i = 0; i < n; i++)
		cin >> arr[i];

	// 오른쪽에서 왼쪽으로 이동 
	for (int i = n - 1; i >= 0; i--){
		while (!s.empty() && (s.top() <= arr[i])){
			s.pop();
		}

		if(s.empty()){
			ans[i] = -1; 
		}else{
			// s.top() > arr[i] 
			ans[i] = s.top(); // top 원소의 값을 저장 
		}

		// 스택의 bottom->top (내림차순)
		s.push(arr[i]); 
	}
	
	for (int i = 0; i < n; i++)
		cout << ans[i] << " ";
}

스택을 어떻게 사용한다는 건가!

예제 입력1을 생각해보자.

4
3 5 2 7

i는 n-1부터 0으로 줄어드는데, n-1일 때 스택이 비어있으므로 ans[i]에는 -1을 저장한다.

arr[3]에 해당하는 7을 스택에 push 한 뒤에, arr[2]와 스택의 top을 비교했을 때 스택의 top이 더 크기 때문에 ans[2]에 7을 저장한다.

arr[1]과 스택의 top을 비교하면, arr[1]의 값이 더 크므로 스택의 top 원소를 pop 함수로 빼준다!

스택의 top인 7과 arr[1]을 비교했을 때, top이 더 크므로 ans[1]에 7을 저장하고, arr[1]을 스택에 push한다.

드디어 마지막! 이번에는 스택의 top이 더 크므로 ans[0]에 5를 저장한다.

최종 결과!

마무리

이중 for문으로 오큰수를 구하면 시간복잡도가 O(N²)이고 N의 최댓값이 100만이므로 100만*100만은 시간 초과가 발생한다. 그러나 스택을 통한 풀이는 시간복잡도가 O(N)이므로 시간 초과 없이 통과가 가능하다!

하지만 그 아이디어를 생각해내기가 정말 쉽지 않은 거 같다,, 앞으로 더 많은 연습이 필요하다!!!

profile
Keep Going!

0개의 댓글