백준 알고리즘

15. 17299번 오등큰수

Romenest 2021. 9. 22. 18:26

 

문제 이해

저번 17298번 오큰수 문제는 해당 숫자보다 오른쪽에 있으면서 그 숫자보다 큰숫자들 중에서 제일왼쪽에 있는 수를 고르는 것이였다면

 

이번 17299번 오등큰수 문제는 해당 숫자의 수량보다 오른쪽에 있으면서 그 숫자의 수량보다 큰 수량들 중에서 가장 왼쪽에 있는 수를 고르는 것이다.

 

즉 입력받는 숫자를 비교하는 것이아닌 입력받은 숫자를 한번더 가공해서 비교하여 결과를 도출해 내는 것이라 할 수 있겠다.

 

  명령받은수 7            
수열 A의 값 1 1 2 3 4 2 1
수열 A의 값들의 수량 3 3 2 1 1 2 3

예제를 받으면 위와 같다

위 예제를 실행하게되면 아래와 같은 결과가 나와야한다

-1 -1 1 2 2 1 -1

실질적으로 비교할 수는

1 1 2 3 4 2 1 이 아닌

 

3 3 2 1 1 2 3 이라고 봐야 한다는 것

 

따라서 나는 3 3 2 1 1 2 3 으로 가공 할 수 있게끔 하나의 배열을 더 추가했다

int N = Integer.parseInt(br.readLine());

int[] A = new int[N];
int[] B = new int[N];
int[] C= new int[???];

A는 명령받은 수 들이 들어갈 배열
B는 결과 값이 들어갈 배열
C는 A를 가공해 넣어둘 배열

이때 포인트는 1 1 2 3 4 2 1 에서 

1은 3개

2는 2개

3은 1개

4는 1개 일때 이것들을 어떻게 정의해서 넣는가 이다

 

C[A[n]] = C[A[n]]+1;

이렇게 반복문을 돌리면 어떨까 하고 고심끝에 생각해냈다.

반복이 돌아간다면 아래와 같을것이다

C[A[0]] = C[A[0]] + 1;
이때 A[0]은 1
따라서 C[1] = C[1] + 1;
A[0] 값인 1이 C에 들어갈때마다 C[1]에 1을 추가한다. 다음으로

C[A[1]] = C[A[1]] + 1;
A[1]은 1
C[1] = C[1] + 1;
위에서 이미 1이 추가되었으므로 C[1]은 2가 된다. 다음으로

C[A[2]] = C[A[2]] + 1;
A[2]는 2
C[2] = C[2] + 1;
C[2]는 이전에 아무값이 없었으므로 1이 추가되어 1이된다.

이제 대강 그림이 보이지않는가?

위와같이 반복하게되면 C[1] , C[2], C[3], C[4] 가 생길것이고

이때의 1,2,3,4는 각각 A배열의 값과 동일하게 된다.

따라서 C[1]은 값 1의 개수

C[2]는 값 2의 개수

C[3]은 값 3의 개수

C[4]는 값 4의 개수가 되겠다.

 

이제 이를 17298번 오큰수에서 풀었던 코드에서 살짝만 수정해주면 가능 할 것이다.

 

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Stack;
 

public class training2 {

	public static void main(String[] args) throws Exception {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        Stack<Integer> stack = new Stack<>();

        //입력받는 명령의 수
        int N = Integer.parseInt(br.readLine());
        
        //입력받은 수가 들어갈 배열A
        int[] A = new int[N];
        
        //결과값이 들어갈 배열 B
        int[] B = new int[N];
        
        //A배열의 값들의 개수를 파악할 배열C
        int[] C = new int[1000001];
        //이때의 1000001은 문제에서 주어진 명령의수가 최대일때를 가정하에 만들었다
        


        for (int i = 0; i < N; i++){
            B[i] = -1;
        }
        //결과 배열의 모든값을 -1로 초기화 

        
        String[] arr = br.readLine().split(" ");
        stack.push(0);
        // 입력받을 수들을 받아 A배열에 넣는 과정
        for (int i = 0; i< N; i++) {
        A[i] = Integer.parseInt(arr[i]);
        }
        
        // A값의 개수를 확인하는 C배열
        for (int i = 0; i< N; i++) {
        C[A[i]] = C[A[i]] +1;
        }

        for (int i = 1; i < N; i++) {
        	if(stack.isEmpty()){
            	stack.push(i);
            }
            while (!stack.isEmpty() && C[A[i]] > C[A[stack.peek()]]) {
                //스택의 가장 윗부분의 값과 비교해서 클때까지 반복

                B[stack.pop()] = A[i];  
            }
            stack.push(i);
        }

        for (int i = 0; i < N; i++){
            bw.write(B[i] + " ");
            //결과값
        }
         
        bw.flush();
        bw.close();
    }
}

결과