[이것이 코딩 테스트다.Part02.Chapter03] - 숫자 카드 게임 (Java)

uHan2·2020년 11월 13일
1

TIL.Algorithm

목록 보기
8/12

안녕하세요.
지금까지 계속 저만의 기술 블로그를 만들어야지, 만들거야
마음으로만 다짐하다가 인제야 시작하게 되었습니다.
비록 시작은 코딩일기지만, 그 끝은 창대하게
어엿한 개발자 블로그로 성장할 수 있도록 노력하겠습니다.


Prologue

안녕하세요!
지난번 작성한 포스트에 이어서 나동빈 저자의 [이것이 코딩 테스트다] 문제 정리 포스트입니다.

[숫자 카드 게임]

<문제>
숫자 카드 게임은 여러 개의 숫자 카드 중에서 가장 높은 숫자가 쓰인 카드 한 장을 뽑는 게임이다. 단, 게임의 룰을 지키며 카드를 뽑아야 하고 룰은 다음과 같다.

  1. 숫자가 쓰인 카드들이 N x M 형태로 놓여 있다. 이때 N은 행의 개수를 의미하며, M은 열의 개수를 의미한다.
  2. 먼저 뽑고자 하는 카드가 포함되어 있는 행을 선택한다.
  3. 그다음 선택된 행에 포함된 카드들 중 가장 숫자가 낮은 카드를 뽑아야 한다.
  4. 따라서 처음에 카드를 골라낼 행을 선택할 때, 이후에 해당 행에서 가장 숫자가 낮은 카드를 뽑를 것을 고려하여 최종적으로 가장 높은 숫자의 카드를 뽑을 수 있도록 전략을 세워야 한다.

···중략···

카드들이 N x M 형태로 놓여 있을 때, 게임의 룰에 맞게 카드를 뽑는 프로그램을 만드시오.

<입력 조건>

  • 첫째 줄에 숫자 카드들이 놓인 행의 개수 N과 열의 개수 M이 공백을 기준으로 하여 각각 자연수로 주어진다. (1 <= N, M <= 100)

  • 둘째 줄부터 N개의 줄에 걸쳐 각 카드에 적힌 숫자가 주어진다. 각 숫자는 1 이상 10,000 이하의 자연수이다.

<출력 조건>

  • 첫째 줄에 게임의 룰에 맞게 선택한 카드에 적힌 숫자를 출력한다.

<입력 예시>                                                                             <출력 예시>

  • 3 3                                                                                           2
    3 1 2
    4 1 4
    2 2 2

  • 2 4                                                                                           3
    7 3 1 8
    3 3 3 4


PseudoCode

처음 문제를 봤을 때 들었던 생각은

(1) 2차원 배열을 써야하나..? 하고 작성 도중 전략 수정

1. 숫자를 공백포함하여 한 줄씩 받아서 가장 작은 수를 구해 배열에 넣는다.

2. 1.의 방식을 N번 반복한다.

3. 각 줄의 가장 작은 값을 배열을 정렬하여 가장 큰 수를 출력한다.

입니다.

처음에 2차원 배열을 써야하나 싶어 풀어보다가 굳이 안써도 될 것 같아 방식을 달리하였습니다.


SourceCode

import java.util.*;
import java.io.*;

public class Main
{
    public static void main(String[] args) throws Exception
    {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());

        int row = Integer.parseInt(st.nextToken());
        String[] minArr = new String[row];

        for(int i = 0; i < row; i++)
        {
            String s = br.readLine();
            String[] arr = s.split(" ");

            Arrays.sort(arr);

            minArr[i] = arr[0];
        }

        Arrays.sort(minArr);
        System.out.println(minArr[row-1]);
    }
}

(언제나처럼 코드리뷰! 부탁드립니다!)

수도코드를 그대로 구현하였으며 길이는 짧습니다. (그래도 파이썬보다는 기네요..)

코드를 살펴보면,


BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());

int row = Integer.parseInt(st.nextToken());
String[] minArr = new String[row];

우선 필요한 변수들을 몇 가지 선언 및 초기화하는 파트입니다.
값을 입력받을 때는 BufferedReader를 이용하였습니다.
또한 값이 3 1 2 이런식으로 값이 들어와서 이를 하나씩 떼어 배열에 넣어줄
StringTokenizer 또한 이용하였습니다.

변수들로는,

  • 카드 배열이 몇 행인지에 대한 변수 row
  • 각 줄의 최소값을 담을 배열 minArr[ ]

이 있습니다.


    for(int i = 0; i < row; i++)
    {
        String s = br.readLine();
        String[] arr = s.split(" ");

        Arrays.sort(arr);
        
        minArr[i] = arr[0];
    }

    Arrays.sort(minArr);
    System.out.println(minArr[row-1]);

다음은 각 줄의 최소값을 배열 minArr[ ]에 담고 정렬 후 가장 큰 수를 출력하는 부분입니다.

  1. 먼저 한 줄을 그냥 String 으로 받고 공백을 기준으로 잘라서 배열 arr[ ] 에 넣었습니다.

  2. 그리고 Arrays.sort() 함수를 이용해서 정렬하고 기본이 오름차순이기 때문에 배열 arr[ ] 첫 인덱스 값을 최소값 보관용인 minArr[ ]에 넣었습니다.

  3. 그렇게 row 크기 만큼 반복 후 각 줄의 최소값인 모인 minArr[ ]을 정렬하여 가장 큰 수를 출력하게 해서 마무리 지었습니다.

풀이는 수도코드를 그대로 구현하였고 길이도 짧아서 이것으로 마무리입니다.

여기서 만약 예전이었다면 저는 arr[ ]int형 배열로 선언하고, Integer.parseInt() 로 각 줄의 값을 숫자로 해서 넣었을 텐데 생각해보니 그냥 String으로 받고 split() 함수를 사용해도 동일하게 할 수 있겠다고 판단되어 문자열로 풀어보았습니다. 혹시 해당 방식에 피드백을 주실 분이 있다면 감사드리겠습니다.


Epilogue

구현 난이도가 낮아 문제를 풀어보는데에 의의를 둔 문제였습니다. 다만, 나동빈 저자의 java 문제풀이 소스코드를 보면 제 풀이와는 달리 2중 반복문을 활용하여 문제를 풀었는데 처리시간에 있어서 저의 방식과 어떻게 얼마나 차이가 나는지 한 번 비교해보는 시간도 갖도록 해보겠습니다.

코드에 대한 조언은 언제나 환영이며, 오히려 부탁드리겠습니다.

profile
For the 1% inspiration.

0개의 댓글