코딩테스트

[BOJ_17298/JAVA] 오큰수

Eun 2021. 12. 19. 19:02

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

문제

 

풀이

처음에는 뒤에 처음 나오는 큰수로 그냥 출력하기만 하면 된다고 생각했다. 하지만 구현하다보니 시간초과가 날 것 같아 방법을 바꿨다.

(그리고 풀리지도 않음 ㅋ)

 

방법을 찾아보니 stack을 이용해서 다들 풀었더라?... 이걸 어떻게 스택으로 풀지?

아직도 문제를 보고 이걸 스택으로 풀어야겠다는 감이 안잡혀 ㅠㅠ

그래도 사람들이 푼 방법을 보고 최대한 이해하고 다시 내가 짜서 해보았다....

 

스택에 가장 윗부분(peek)과 배열의 원소를 비교해서 배열의 원소가 크면, pop을 한 인덱스 값을 큰 배열의 원소로 바꿔주면 된다.

이게 무슨 소리냐...면

 

arr = {3,5,2,7}

1. 맨 처음에 3을 그냥 push. 이때 3의 인덱스는 0이니까 0을 push한다. (이유는 나중에 나옴)

2. 그 다음 원소인 5와 stack.peek()을 해서 비교했을 때 5가 더 크니까 pop하고 5의 인덱스인 1을 넣음.

그리고 pop한 인덱스(0)을 5로 바꾼다. (arr[0] = 5)

3. 5(peek)와 2를 비교했을 때 2가 작으니까 push를 한다. 이때도 2의 인덱스(2)를 push한다.

4. 7이랑 2(peek)와 비교했을 때 7이 더 크니까 2를 pop하고 arr[2]=7로 값 바꿈. 

이것을 while문으로 7보다 작은 값들을 반복함. 

5. 배열을 다 탐색하고 스택에 값이 남아있으면 큰 수가 없다는 의미이므로 -1 출력

6. 최종적으로 arr={5,7,7,-1} 이 된다.

 

여기서 핵심은 배열의 값이 아닌 index를 스택에 넣는다는 것이다.

그 이유는 배열의 Index값을 알아야 배열의 원소를 바꿔줄 수 있기때문이다.

 만약, 배열의 값을 저장했다면 배열의 값과 일치하는 인덱스를 찾아 다 뒤져 바꿔줘야하기때문에 시간을 절약할 수 있다.

 

코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Stack;
import java.util.StringTokenizer;

public class BOJ17298 {

	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringBuilder sb = new StringBuilder();
		StringTokenizer st;
		Stack<Integer> stack = new Stack<>();
		
		int num = Integer.parseInt(br.readLine());
		int [] arr = new int[num];
		
		st = new StringTokenizer(br.readLine());
		
		int j=0;
		
		while(st.hasMoreTokens()) {
			arr[j]=Integer.parseInt(st.nextToken());
			j++;
		}

		stack.push(0);
		
		for(int i = 1; i < num; i++) {
			
			
			if(stack.isEmpty()) {
				stack.push(i);
			}
			
			while(!stack.isEmpty() && arr[stack.peek()] < arr[i]) {
				arr[stack.pop()] = arr[i];
			}
			
			stack.push(i);
		}
		
		while(!stack.isEmpty()) {
			arr[stack.pop()] = -1;
		}
		
		for(int i = 0; i < num; i++) {
			sb.append(arr[i]).append(' ');
		}
		
		System.out.println(sb);

	}

}

 


이번 문제는 골드 4 문제여서 어려웠다 ... ㅠ

이해는 했지만 이걸 어떻게 풀지...? 라는 의문만 가득...