강의

멘토링

커뮤니티

Cộng đồng Hỏi & Đáp của Inflearn

Hình ảnh hồ sơ của a939518771
a939518771

câu hỏi đã được viết

Bí quyết đỗ 38 nơi, các thuật toán bắt buộc cho kỳ thi Coding Test 2025

1-5. Làm quen với thuật toán (2)

1-5 알고리즘과 친해지기 (2) - 최빈값찾기 질문 있습니다

Viết

·

64

·

Đã chỉnh sửa

0

1. 현재 학습 진도

  • 몇 챕터/몇 강을 수강 중이신가요?

    • 8.1-5 알고리즘과 친해지기 (2) - 최빈값찾기

  • 어떤 알고리즘을 학습하고 계신가요?

    • 최빈값 찾기

       

2. 어려움을 겪는 부분

  • 어느 부분에서 막히셨나요?

    • 왜 배열로 푸는 것이 제일 낫나요?

    • 저는 java의 map을 사용해서 풀었는데 이건 좋지 않은 풀이법일까요?

       

 

3. 시도해보신 내용

  • 현재 작성하신 코드를 공유해주세요

public class FindMaxOccurredAlphabet0102 {
  public static void main(String[] args) {
    System.out.println("정답 = i 현재 풀이 값 = " + solution("hello my name is dingcodingco"));
    System.out.println("정답 = e 현재 풀이 값 = " + solution("we love algorithm"));
    System.out.println("정답 = b 현재 풀이 값 = " + solution("best of best youtube"));
  }

  public static char solution(String s) {
    Map<Character, Integer> map = new HashMap<>();
    for (int i = 0; i < s.length(); i++) {
      char c = s.charAt(i);
      if (!Character.isLetter(c)) {
        continue;
      }
      map.put(c, map.getOrDefault(c, 0) + 1);
    }
    List<Map.Entry<Character, Integer>> list = new ArrayList<>(map.entrySet());
    list.sort(
        (a, b) -> b.getValue() - a.getValue()
    );
    return list.get(0).getKey();
    }
}
python코딩-테스트알고리즘data-structure지금-베스트

Câu trả lời 2

2

dingcodingco님의 프로필 이미지
dingcodingco
Người chia sẻ kiến thức

안녕하세요 지협님! 좋은 질문 감사합니다! 직접 풀어보고 "왜 배열이 더 나을까?"라고 고민하는 과정 자체가 실력을 키우는 데 정말 좋은 습관입니다

1. 왜 배열로 푸는 것이 "제일 낫다"고 하는가?

결론부터 말씀드리면, 이 문제에서 배열이 권장되는 이유는 "알파벳은 a~z까지 딱 26개로 고정"이라는 특성 때문이에요.

alphabet_occurrence_array = [0] * 26 이렇게 길이 26짜리 배열을 만들면, 'a'는 0번 인덱스, 'b'는 1번 인덱스... 이런 식으로 아스키코드 계산(ord(char) - ord('a'))만으로 바로 접근할 수 있어요. 마치 캡슐호텔에서 번호만 알면 바로 방을 찾는 것처럼요.

이 방식의 장점은 크게 세 가지예요.

첫째, 추가적인 자료구조가 필요 없어요. 단순 int 배열 하나면 충분하기 때문에 메모리 오버헤드가 거의 없어요. HashMap은 내부적으로 해시 버킷, Entry 객체, 링크드리스트 등 부가적인 구조를 만들어야 하거든요.

둘째, 접근 속도가 순수 O(1)이에요. 배열의 인덱스 접근은 메모리 주소를 직접 계산해서 바로 가는 거라서, HashMap의 해시 계산 → 버킷 찾기 → 키 비교 과정보다 실제 실행 속도가 빨라요. 빅오 표기법으로는 둘 다 O(1)이지만, 상수 시간의 크기가 다른 거죠.

셋째, "최빈값이 여러 개일 경우 알파벳 순서가 앞인 것을 반환"하라는 조건을 자연스럽게 처리할 수 있어요. 배열은 인덱스 0(a)부터 순서대로 돌기 때문에, 같은 빈도수면 먼저 만난 게 자동으로 알파벳 순 앞쪽이에요. HashMap은 순서를 보장하지 않아서 별도의 정렬 처리가 필요하죠.

정리하면, 이 문제처럼 "저장해야 할 키의 범위가 고정되어 있고, 그 범위가 작을 때"는 배열이 가장 단순하고 효율적인 선택이에요. 강의에서 이 풀이를 가르치는 이유도, 알고리즘 문제에서 이런 "고정 범위 → 배열 매핑" 패턴이 굉장히 자주 나오기 때문이에요.

 

2. Map을 사용한 풀이가 좋지 않은 풀이인가?

전혀 나쁜 풀이가 아니에요! 오히려 실무적으로 보면 HashMap을 쓰는 게 더 자연스러운 경우가 많아요. 코드를 보면 getOrDefault도 잘 활용하고 계시고, 로직도 깔끔해요.

다만 몇 가지 차이점은 알아두면 좋아요.

시간복잡도 측면에서, 지협님의 코드에서 마지막에 list.sort()로 정렬하는 부분이 O(K log K) (K는 등장한 알파벳 수)를 추가로 소요해요. 배열 풀이는 그냥 26개를 순회하면서 최댓값을 찾으니 O(26) = O(1)이고요. 물론 K가 최대 26이라 실질적인 차이는 거의 없지만, 정렬 없이도 풀 수 있다는 점은 알아두시면 좋아요.

만약 Map으로 풀되 정렬 없이 하고 싶다면 이렇게도 가능해요:

public static char solution(String s) {
    Map<Character, Integer> map = new HashMap<>();
    for (int i = 0; i < s.length(); i++) {
        char c = s.charAt(i);
        if (!Character.isLetter(c)) continue;
        map.put(c, map.getOrDefault(c, 0) + 1);
    }

    char maxChar = 'z';
    int maxCount = 0;
    for (Map.Entry<Character, Integer> entry : map.entrySet()) {
        // 빈도가 더 크거나, 같으면 알파벳 순서가 앞인 것을 선택
        if (entry.getValue() > maxCount ||
            (entry.getValue() == maxCount && entry.getKey() < maxChar)) {
            maxCount = entry.getValue();
            maxChar = entry.getKey();
        }
    }
    return maxChar;
}

이러면 정렬 없이 O(N) 한 번에 해결돼요.

3. 그러면 언제 배열을, 언제 Map을 쓰는 게 좋을까?

이 판단 기준을 갖고 가시면 앞으로 비슷한 문제에서 바로 적용할 수 있어요.

배열이 유리한 경우: 키의 범위가 고정되고 작을 때 (알파벳 26개, 숫자 0~9, ASCII 128개 등). 이런 문제를 만나면 "배열로 매핑하면 되겠다!"라고 바로 떠올리시면 돼요.

Map이 유리한 경우: 키의 범위를 예측할 수 없거나 범위가 매우 클 때 (예: 단어별 빈도수 세기, 좌표 매핑 등). 이런 경우는 배열을 잡기 어려우니 Map이 자연스러워요.

지협님이 Map으로 먼저 풀어본 건 정말 좋은 접근이에요. 실제 코딩테스트에서는 Map으로 풀어도 충분히 통과하는 경우가 대부분이거든요. 다만 이 강의에서 배열 풀이를 강조하는 건, "고정 범위 → 배열 매핑"이라는 핵심 패턴을 익히게 하려는 의도예요. 이 패턴을 알아두면 나중에 더 복잡한 문제에서 응용할 수 있거든요.

Java에서 배열로 풀어보고 싶으시다면 이런 식으로 작성할 수 있어요

public static char solution(String s) {
    int[] count = new int[26]; // 알파벳 26개 고정 배열
    for (int i = 0; i < s.length(); i++) {
        char c = s.charAt(i);
        if (!Character.isLetter(c)) continue;
        count[c - 'a']++; // 아스키코드로 인덱스 매핑
    }

    int maxIndex = 0;
    for (int i = 1; i < 26; i++) {
        if (count[i] > count[maxIndex]) {
            maxIndex = i;
        }
    }
    return (char) (maxIndex + 'a');
}

Python의 ord(char) - ord('a')가 Java에서는 c - 'a'로 더 간단하게 표현돼요. Java는 char 타입이 숫자로 바로 연산되니까요.

두 가지 방식 모두 직접 구현해보시면 "아, 이래서 배열이 깔끔하구나"를 체감하실 수 있을 거예요. 이해 안 되는 부분 있으면 언제든 또 질문해주세요!

a939518771님의 프로필 이미지
a939518771
Người đặt câu hỏi

상세한 답변 감사드립니다

0

안녕하세요, 인프런 AI 인턴입니다. 김지협님.

질문해주신 내용은 최빈값 찾기에 대한 다양한 접근 방식입니다. Java의 Map을 사용하여 문제를 풀어주셨는데요, 이 방법은 충분히 좋은 방법입니다. 다만 배열과 비교하여 각각의 장점과 단점이 있기에 이를 잘 이해하고 활용하는 것이 중요합니다.

배열과 Map의 차이

  1. 배열:

    • 고정 길이: 배열은 정해진 크기를 가지고 있습니다. 따라서 메모리 사용이 고정적이며, 효율적인 면이 있습니다. 예를 들어, ASCII 알파벳의 경우 크기는 26으로 고정되며, 직관적으로 알파벳의 빈도를 세는 데 용이합니다.
    • 빠른 접근: 인덱스를 통해 빠르게 접근 가능하여, 특정한 경우 더 빠른 성능을 발휘할 수 있습니다.
  2. Map:

    • 유연성: 다양한 자료형의 키를 사용할 수 있고, 크기가 동적이어서 입력 데이터에 따라 유연하게 크기를 조정할 수 있습니다.
    • 가독성: 키-값 쌍을 사용하므로 읽고 이해하기가 쉬울 수 있습니다.

Java 코드 평가

  • 가독성과 직관성: Map을 사용하여 알파벳의 빈도를 계산하고, 정렬하여 최빈 알파벳을 찾는 방식은 가독성이 좋고 이해하기 쉽습니다.
  • 다양한 데이터 처리: 다양한 입력 데이터 형태를 처리할 수 있어 범용성이 높습니다.

하지만 이 코드에서는 사전 순으로 가장 앞에 위치한 알파벳을 반환하지 않고, 값들이 정렬되어 있는 순서에 따라 가장 높은 빈도의 첫 번째 문자를 반환합니다. 동일한 빈도의 알파벳이 있을 때 사전 순으로 먼저 오는 문자를 반환하는 기능이 필요하다면, 조금 더 수정이 필요할 수 있습니다.

참고할 만한 자료

최빈값 찾기에 대해 다양한 방법을 다룬 기존 답변을 참고하시면 좋습니다:

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

Hình ảnh hồ sơ của a939518771
a939518771

câu hỏi đã được viết

Đặt câu hỏi