본문 바로가기
코딩테스트

[백준]1157번 단어공부 - java[자바]

by 어썸오184 2020. 12. 26.
728x90
반응형

문제

단어공부

단어가 주어지면 가장 많이 사용된 알파벳을 반환하는 문제이다. 가장 많이 사용된 알파벳이 2개 이상이면 ?를 반환한다. 대소문자를 구분하지 않는다.

입출력 예

입력 출력
Mississipi ?
zZa Z
z Z
baaa A

풀이 및 접근방법

문제를 보자마자 알파벳을 Key로 사용횟수를 Value로 하는 Map을 만들어서 이용하면 쉽게 풀이할 수 있겠다는 생각이 들었다.

너무 뻔한 풀이 같아서 각 알파벳의 아스키코드를 인덱스로 해서 사용횟수를 배열에 저장해서 풀어보려 했는데, 가장 많이 사용된 알파벳의 숫자가 두 개 이상인 경우에 코드가 복잡해져서 포기하고 그냥 Map을 사용했다.

코드

import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.stream.Collectors;

public class Main {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String input = scanner.nextLine();
        char mostFrequentAlphabet = findMostFreqAlphabet(input);
        System.out.println(mostFrequentAlphabet);
    }


    public static char findMostFreqAlphabet(String text) {
        Map<Character, Integer> record = parseToMap(text);

        List<Entry<Character, Integer>> sortedEntry = sortByValue(record);

        if (sortedEntry.size() > 1 && isDuplicate(sortedEntry)) {
            return '?';
        }

        return sortedEntry.get(0).getKey();
    }

    private static Map<Character, Integer> parseToMap(String text) {
        Map<Character, Integer> map = new HashMap<>();
        String alphabets = text.toUpperCase();
        for (int i = 0; i < alphabets.length(); i++) {
            char key = alphabets.charAt(i);
            map.put(key, map.getOrDefault(key, 0) + 1);
        }
        return map;
    }

    private static List<Entry<Character, Integer>> sortByValue(Map<Character, Integer> record) {
        return record.entrySet().stream()
            .sorted(Entry.comparingByValue(Comparator.reverseOrder()))
            .collect(Collectors.toList());
    }

    private static boolean isDuplicate(List<Entry<Character, Integer>> sortedEntry) {
        return sortedEntry.get(0).getValue().equals(sortedEntry.get(1).getValue());
    }
}

기억하고 넘어가면 좋을 부분은 알파벳의 사용 횟수를 맵에 저장하는 부분과 사용 횟수를 기준으로 정렬하는 부분이다.

getOrDefault(key, defaultValue)

    private static Map<Character, Integer> parseToMap(String text) {
        Map<Character, Integer> map = new HashMap<>();
        String alphabets = text.toUpperCase();
        for (int i = 0; i < alphabets.length(); i++) {
            char key = alphabets.charAt(i);
            map.put(key, map.getOrDefault(key, 0) + 1);
        }
        return map;
    }

값을 설정하는 부분에서 getOrDefault(key, defaultValue) 를 이용하면 맵에 해당 키가 없는 경우 초기값을 설정하고 있으면 해당 값을 반환한다.

현재 값을 반환한 후 1을 더해줘서 사용 횟수를 저장할 수 있다.

Map 정렬하기

    private static List<Entry<Character, Integer>> sortByValue(Map<Character, Integer> record) {
        return record.entrySet().stream()
            .sorted(Entry.comparingByValue(Comparator.reverseOrder()))
            .collect(Collectors.toList());
    }

정확히 말하면 Map을 정렬하는건 아니고 맵에 저장된 엔트리 셋을 정렬된 리스트로 반환하는 방법이다. 가장 많이 사용된 알파벳을 찾기 위해서 정렬을 한번 해줘야 하는데, Map은 순서정보를 저장하지 않기 때문에 이같은 방법을 사용했다.

Map.EntrycomparingByValue를 이용하면 값을 기준으로 정렬할 수 있다. 이때 오름차순으로 정렬되는데, 우리는 최대값이 필요하므로 내림차순으로 정렬한다. 내림차순으로 정렬하려면 Comparator로 reverseOreder를 넘겨주면 된다.

728x90
반응형

댓글