본문 바로가기

코딩테스트

[JAVA] 백준 4358번 - 생태학

728x90
 

문제

 

생태학에서 나무의 분포도를 측정하는 것은 중요하다. 그러므로 당신은 미국 전역의 나무들이 주어졌을 때, 각 종이 전체에서 몇 %를 차지하는지 구하는 프로그램을 만들어야 한다.

 

입력

 

프로그램은 여러 줄로 이루어져 있으며, 한 줄에 하나의 나무 종 이름이 주어진다. 어떤 종 이름도 30글자를 넘지 않으며, 입력에는 최대 10,000개의 종이 주어지고 최대 1,000,000그루의 나무가 주어진다.

 

출력

주어진 각 종의 이름을 사전순으로 출력하고, 그 종이 차지하는 비율을 백분율로 소수점 4째자리까지 반올림해 함께 출력한다.

 

예제 입력 1 복사

Red Alder
Ash
Aspen
Basswood
Ash
Beech
Yellow Birch
Ash
Cherry
Cottonwood
Ash
Cypress
Red Elm
Gum
Hackberry
White Oak
Hickory
Pecan
Hard Maple
White Oak
Soft Maple
Red Oak
Red Oak
White Oak
Poplan
Sassafras
Sycamore
Black Walnut
Willow

예제 출력 1 복사

Ash 13.7931
Aspen 3.4483
Basswood 3.4483
Beech 3.4483
Black Walnut 3.4483
Cherry 3.4483
Cottonwood 3.4483
Cypress 3.4483
Gum 3.4483
Hackberry 3.4483
Hard Maple 3.4483
Hickory 3.4483
Pecan 3.4483
Poplan 3.4483
Red Alder 3.4483
Red Elm 3.4483
Red Oak 6.8966
Sassafras 3.4483
Soft Maple 3.4483
Sycamore 3.4483
White Oak 10.3448
Willow 3.4483
Yellow Birch 3.4483

 

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

// BaekJoon 4358 - 생태학
public class Main {
    public static void main(String[] args) throws IOException{

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int count = 0; // 총 나무 개수
        String tree = br.readLine();
        HashMap<String, Integer> trees = new HashMap<>();
        trees.put(tree, 1); // 제일 첫번째 나무를 넣어준다
        count++;

        while ((tree = br.readLine()) != null) { // br이 없을 때까지 반복
            if (tree.isEmpty()) // 더 이상 입력 받을게 없으면 종료
                break;

            if (trees.containsKey(tree)){ // 다음번 나무가 map에 있는지 확인한다, True면 존재하는 것
                int treeCount = trees.get(tree); // 나무 key를 통해 value 찾기
                trees.put(tree, treeCount+1); // value에 + 1 하여 key에 put 해준다
            }else{ // map에 해당 나무가 없으면 ->  처음 등장한 나무면
                trees.put(tree,1); // map에 value 1로 넣어준다
            }
            count++; // 나무개수 증가
        }

        List<String> keys = new ArrayList<>(trees.keySet()); // map의 key들 가져오기
        Collections.sort(keys); // key 오름차순 정렬

        for(String key : keys){ // 출력을 위한 반복문
            if (key != null) {
                System.out.print(key + " "); // 나무 이름 출력
                System.out.printf("%.4f%n", (double)trees.get(key) / count * 100); // 비율을 소수점 4자리까지 출력
            }
        }
    }
}

 

풀이 과정

나무의 이름과 문자열에서 나무의 등장 횟수, 총 2가지를 저장해야하기 때문에 자료구조로 HashMap을 채택했다.
HashMap<String, Integer> trees = new HashMap<>();
String => tree name
Integer => tree count

문자열 예제 입력을 받는 것은 BufferedReadLine에서 readLine을 이용해서 개행문자 "\n" 을 기준으로 구분하여
나무의 이름을 하나씩 받았다. 예제 입력에서 나무의 이름을 최대 몇 개 까지 입력하겠다라는 것이 없기 때문에
while문 loof를 사용하고 조건문으로 readLine의 입력이 있을 때 loof문으로 진입하게 했다.
while문의 탈출 조건을 readLine의 값이 공백인 경우로 설정했다.

만약 readLine이 공백이 아니라면 입력받은 나무의 이름이 HashMap에 존재하는지 체크한다. -> trees.containsKey(tree)
containsKey가 True를 리턴하면 이미 HashMap에 해당 나무 이름이 존재하는 것이므로 해당 나무 이름을 key로 value값을
가져와서 1을 더해준다.
false를 리턴한다면 처음 등장한 나무이므로 나무 이름을 key, value값을 1로 하여 HashMap에 put한다.
출력 조건으로 나무 이름을 사전 순으로 출력하는 것이 있기 때문에 HashMap에 저장된 key(나무 이름)을
ArrayList로 가져와서 오름차순 정렬을 수행해준다.

나무 이름과 함께 각 나무가 차지하는 비율 (해당 나무 수) / (전체 나무 수) * 100을 출력해준다.

막혔던 부분

  1. 최대 입력할 나무 이름 수 조건 없이 문자열만 입력 예제로 받는 것이 어려웠다. 몇 번 반복해야 하는지 모르기 때문에.
    이 부분은 구글링을 통해 예제입력을 개행문자를 기준으로 나누어 반복문 안에 readLine을 써주면 최대 반복 횟수가 없어도 입력 받을 수 있다는 것을 알았다.
  2. Map 자료구조가 많이 써본적이 없는 어색한 자료구조여서 Map에서 사용할 수 있는 메서드들을 구글링을 이용하여 알아내고 풀었다.
728x90
반응형