본문 바로가기
온라인 저지/BOJ

[BOJ/Java] 2493 탑

by ahj 2022. 2. 9.

1차 시도

stack 문제이길래 순진하게도 그냥 stack으로만 하면 속도가 나오는 줄 알았다.

생각한대로 구현은 어찌저찌 해냈다. 하지만 6%에서 시간 초과... 생각해보면 당연하다. pop, push 계속 일어나고.. stack도 3개나 쓰고. 그래서 stack 사용을 포기 하고 그냥 완전탐색 방향으로 선회했다.

 

-> 코드 변수가 너무 많아지고 복잡해지면 잘못 가고 있다는 사실을 깨닫자..

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

public class BOJ2493_1st_Failure {

	public static void main(String[] args) throws Exception {
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		StringBuilder sb = new StringBuilder();

		int n = Integer.parseInt(in.readLine());
		Stack<int[]> stackOrigin = new Stack<int[]>(), stackTemp = new Stack<int[]>();
		StringTokenizer st = new StringTokenizer(in.readLine());
		for (int i = 1; i <= n; i++) {
			stackOrigin.push(new int[] { Integer.parseInt(st.nextToken()), i });

		}
		int[] taken = null, nextTaken, answer = new int[n];
		int currentIndex = n - 1;
		boolean flag = true;
		while (true) {
			// 6. stack 모두 empty면 탈출
			if (stackOrigin.isEmpty() && stackTemp.isEmpty())
				break;
			if (flag == true) {
				taken = stackOrigin.pop();
			}
			// 1. taken과 nextTaken의 높이([0]) 비교
			nextTaken = stackOrigin.pop();
			// 2. 다음 pop이 크면 answer[currentIndex]에다가 nextTaken[1] 할당
			if (nextTaken[0] > taken[0]) {
				answer[currentIndex--] = nextTaken[1];
				stackOrigin.push(nextTaken);
				// 5. stackTemp.isEmpty()가 아니면 
				while (!stackTemp.isEmpty()) {
					// 다시 stackTemp.pop()을 stackOrigin에 push
					stackOrigin.push(stackTemp.pop());
				}
				flag = true;
			}
			// 4. stackOrigin.isEmpty되면 answer[currentIndex]에 0 할당
			else if (stackOrigin.isEmpty()) {
				answer[currentIndex--] = 0;
				// 5. stackTemp.isEmpty()가 아니면 
				while (!stackTemp.isEmpty()) {
					//다시 stackTemp.pop()을 stackOrigin에 push
					stackOrigin.push(stackTemp.pop());
				}
				flag = true;
			}
			// 3. 작으면 stackTemp에다가 push하고 다음 꺼내고 다시 1로
			else {
				stackTemp.push(nextTaken);
				flag = false;
			}
		}
		for (int el : answer) {
			sb.append(el).append(" ");
		}
		in.close();
		System.out.println(sb);
	}

}

 

2차 시도

단순한 탐색 구현이 됐다. 뒤에서부터 앞의 모든 것들을 비교해주고... 비교해주고...

지금 와서 다시 코드를 보니 stack이라는 개념에 꽂혀가지고 다 넣어놓고 비교할 생각을 했던 것 같다.

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

public class BOJ2493_2nd_Failure {

	public static void main(String[] args) throws Exception {
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		StringBuilder sb = new StringBuilder();

		int n = Integer.parseInt(in.readLine());
		int[][] originList = new int[n][2];
		StringTokenizer st = new StringTokenizer(in.readLine());
		for (int i = 0; i < n; i++) {
			originList[i] = new int[] { Integer.parseInt(st.nextToken()), i + 1 };
		}
		int[] answer = new int[n];
		for (int i = n - 1; i > 0; i--) { // 뒤에서부터 보면서
			for (int j = i - 1; j >= 0; j--) { // 앞의 것들이랑 비교해가면서
				if (originList[i][0] < originList[j][0]) {
					answer[i] = originList[j][1];
					break;
				}

			}
		}
		for (int el : answer) {
			sb.append(el).append(" ");
		}
		in.close();
		System.out.println(sb);
	}

}

 

해결 코드

결국 1시간 반이 지나도록 해결하지 못했고 반 동기들과 이야기하는 시간이 찾아왔다. 해결하신 분들이 몇 분 있어서 여러 설명을 듣다보니까 이 문제에서 이용되는 stack의 개념이 와닿아서 들은 설명을 토대로 스스로 한번 구현해봤고 결국은 통과해냈다. 감동

 

입력할때마다 비교를 해주게 되면 시간복잡도를 줄일 수 있다. 매번 입력을 그냥 다 받아놓고 하려니까 결국 완전탐색 방향으로 귀결되는 것.

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

// 중요한 포인트는 입력할 때마다 비교를 수행하는 것 -> 시간 복잡도를 줄이는 방법이 된다.
public class BOJ2493 {

	public static void main(String[] args) throws Exception {
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		StringBuilder sb = new StringBuilder();

		int n = Integer.parseInt(in.readLine()); // 비교할 높이의 개수
		Stack<int[]> stackH = new Stack<int[]>(); // 비교할 높이를 담아 줄 stack
		StringTokenizer st = new StringTokenizer(in.readLine());
		int[] currentH, topH;
		for (int i = 1; i <= n; i++) {
			// 사용해줄 객체 { 높이, index }
			currentH = new int[] { Integer.parseInt(st.nextToken()), i };
			// stack이 비어있지 않을 때 == 현재 높이랑 비교해줄 높이가 stack 안에 있다는 것
			while (!stackH.isEmpty()) {
				topH = stackH.peek(); // stack top
				// 현재 높이보다 top이 높으면 peek의 index를 sb.append
				if (currentH[0] < topH[0]) {
					sb.append(topH[1] + " ");
					// 그 외의 stack 안의 값은 비교할 필요가 없으므로 탈출
					break;
				}
				stackH.pop();
			}
			// stack이 비어있으면 0 넣기
			if (stackH.isEmpty())
				sb.append("0 ");
			stackH.push(currentH);
		}
		in.close();
		System.out.println(sb);
	}
}

'온라인 저지 > BOJ' 카테고리의 다른 글

[BOJ/Java] 1158 요세푸스 문제  (0) 2022.02.10
[BOJ/Java] 13335 트럭  (0) 2022.02.10
[BOJ/Java] 1966 프린터 큐  (0) 2022.02.09
[BOJ/Java] 1991 트리 순회  (0) 2022.02.06
[BOJ/Java] 17478 재귀함수가 뭔가요?  (0) 2022.02.03

댓글