[Java] N번째 큰 수 (백준 2693번)

minjung·2022년 11월 26일
0

📖문제

배열 A가 주어졌을 때, N번째 큰 값을 출력하는 프로그램을 작성하시오.

배열 A의 크기는 항상 10이고, 자연수만 가지고 있다. N은 항상 3이다.

  • 첫째 줄에 테스트 케이스의 개수 T(1 ≤ T ≤ 1,000)가 주어진다. 각 테스트 케이스는 한 줄로 이루어져 있고, 배열 A의 원소 10개가 공백으로 구분되어 주어진다. 이 원소는 1보다 크거나 같고, 1,000보다 작거나 같은 자연수이다.
  • 각 테스트 케이스에 대해 한 줄에 하나씩 배열 A에서 3번째 큰 값을 출력한다.

✏️내 풀이

💡첫 번째 생각

  1. 테스트 케이스 개수 T를 입력받는다.
  2. T번 반복하는 반복문 안에서 아래 순서를 반복한다.
  3. 10개의 데이터를 받아서 배열에 넣는다.
  4. Arrays.sort를 사용해 내림차순으로 정렬한다.
  5. 3번째 값을 출력한다.

이 방법으로 하면 한 번 입력받을 때마다 바로 출력값이 나오게 되므로 오답


💡두 번째 생각

  1. 테스트 케이스 개수 T를 입력받는다.
  2. T번 반복하는 반복문 안에서 아래 순서를 반복한다.
  3. map을 만들고 key값은 i로 한다. value에는 배열은 넣는다.
    3-1. 배열은 내림차순으로 정렬한다.
  4. 위 반복문이 끝나면 아래 순서를 T번 반복한다.
  5. map에서 value를 꺼내고, 배열의 2번째 인덱스값을 출력한다.

이 방법으로 하려다가 굳이 map을 사용할 필요가 없을 것 같아서 아래 방법으로 수정함


💡세 번째 생각

  1. 테스트 케이스 개수 T를 입력받는다.
  2. 각 배열의 3번째 큰 수를 저장할 배열을 생성한다.
  3. 아래 순서를 T번 반복한다.
    3-1. 입력값을 저장할 배열을 생성한다.
    3-2. 입력값을 공백으로 구분해서 string타입의 배열에 저장하고
    3-3. 그 값을 3-1의 배열에 저장한다.
    3-4. 배열을 내림차순으로 정렬하고
    3-5. 3번째로 큰 수(인덱스 2번)를 2의 배열에 저장한다.
  4. 3의 반복문이 끝나면 아래 순서를 T번 반복한다.
    4-1. 2 배열의 값을 출력한다.
package lv_1;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Collections;

public class B2693 {

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

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		//테스트케이스 개수 입력받기
		int t = Integer.parseInt(br.readLine());

		//각 배열의 3번째 큰 수를 저장할 배열 생성
		int[] result = new int[t];

		//10개의 데이터 받기 t번 반복
		for(int i=0;i<t;i++) {

			//입력값을 저장할 배열 생성
			Integer[] arr = new Integer[10];

			//입력값을 공백으로 구분해서 string타입 배열에 저장
			String[] str = br.readLine().split(" ");

			//string 배열 값을 integer 배열에 저장
			for(int j=0;j<10;j++) {
				arr[j] = Integer.parseInt(str[j]);
			}

			//배열을 내림차순으로 정렬
			Arrays.sort(arr, Collections.reverseOrder());

			//3번째로 큰 수를 정답 배열에 저장
			result[i] = arr[2];
		}

		//정답 출력
		for(int i=0;i<t;i++) {
			System.out.println(result[i]);
		}

	}

}

📍다른 풀이

맞힌 사람 코드를 보다가 아래와 같은 코드를 발견했다.

import java.io.*;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        int cnt = Integer.parseInt(br.readLine());

        for (int i = 0; i < cnt; i++) {
            StringTokenizer st = new StringTokenizer(br.readLine());
            int[] arr = new int[10];
            for (int j = 0; j < arr.length; j++) {
                arr[j] = Integer.parseInt(st.nextToken());
            }
            Arrays.sort(arr);

            bw.write(arr[arr.length - 3] + "\\n");
        }

        bw.close();
        br.close();
    }
}

StringTokenizer에 대해 찾아보니 spilt과 같은 역할을 한다는 것을 알게 되었다.
spilt을 사용하면 그 값을 배열에 저장한 후 그 값을 다시 숫자 배열에 넣어야 했는데, StringTokenizer를 사용하면 그 과정을 생략해도 되는 것 같았다.
그래서 이 방법을 내 코드에도 적용해보았다.

💡네 번째 생각

package lv_1;

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

public class B2693 {

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

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		//테스트케이스 개수 입력받기
		int t = Integer.parseInt(br.readLine());

		//각 배열의 3번째 큰 수를 저장할 배열 생성
		int[] result = new int[t];

		//10개의 데이터 받기 t번 반복
		for(int i=0;i<t;i++) {

			//입력값을 저장할 배열 생성
			int[] arr = new int[10];

			//StringTokenizer 사용해서 공백으로 데이터 구분하기
			StringTokenizer st = new StringTokenizer(br.readLine());

			//배열에 각 데이터 넣기
			for(int j=0;j<10;j++) {
				arr[j] = Integer.parseInt(st.nextToken());
			}

			//오름차순으로 정렬
			Arrays.sort(arr);

			//3번째로 큰 수를 정답 배열에 저장
			result[i] = arr[arr.length - 3];
		}

		//정답 출력
		for(int i=0;i<t;i++) {
			System.out.println(result[i]);
		}
	}
}

그 결과 코드의 길이가 766B -> 728B로 짧아지고, 시간도 184ms -> 172ms로 단축!


🤓배운 점

공백 단위로 데이터 구분하기

  • StringTokenizer

StringTokenizer 클래스는 문자열을 우리가 지정한 구분자로 문자열을 쪼개주는 클래스이다.

코드설명
StringTokenizer(String str)str을 기본 구분자로 분리한다. 기본 구분자는 공백문자이다. (\t, \n, \r, \t)
StringTokenizer(String str, String delim)특정 구분자로 문자열을 분리한다.

데이터를 가져오고 싶을 때는 String nextToken()을 사용한다.


배열 내림차순 정렬

  • Collections.reverseOrder()

Arrays.sort()를 사용하면 배열을 오름차순 정렬할 수 있다.
만약 배열을 내림차순으로 정렬하고 싶다면 매개변수에 Collections.reverseOrder()을 추가해주면 된다. (아래 코드처럼 적용한다.)

Arrays.sort(arr, Collections.reverseOrder());

이 때 배열의 타입은 Integer여야 한다.


참고링크

[자바/JAVA] STRINGTOKENIZER를 이용해 문자열을 쪼개보자

0개의 댓글