본문 바로가기
알고리즘 공부/백준

[JAVA 백준 19일차 / 하루 3문제] 1157번, 2941번, 1316번

by maverick11471 2025. 2. 20.

1. 1157번 단어공부

 가. 스트림을 사용하지 않은 경우

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String s = br.readLine().toUpperCase();
        int[] counts = new int[26];
        
        // 각 문자 빈도수 계산
        for (char c : s.toCharArray()) {
            counts[c - 'A']++;
        }
        
        // 최대 빈도수 찾기
        int max = 0;
        for (int count : counts) {
            if (count > max) max = count;
        }
        
        // 최대 빈도수 중복 확인
        int maxCount = 0;
        char result = '?';
        for (int i = 0; i < counts.length; i++) {
            if (counts[i] == max) {
                maxCount++;
                result = (char) (i + 'A');
            }
        }
        
        System.out.println(maxCount > 1 ? '?' : result);
    }
}
  • counts[26]: A-Z를 0-25로 매핑해 빈도수 저장
  • c - 'A': 알파벳을 숫자로 변환해 배열 인덱스로 사용
    • H  72 - 65  7  counts[7]++
    • E  69 - 65  4  counts[4]++
    • L  76 - 65  11  counts[11]++
    • O  79 - 65  14  counts[14]++

 나. 스트림을 사용 한 경우

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Map;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String s = br.readLine().toUpperCase();
        
        // 문자 빈도수 맵 생성
        Map<Character, Long> frequencyMap = s.chars()
                .mapToObj(c -> (char) c)
                .collect(Collectors.groupingBy(c -> c, Collectors.counting()));
        
        // 최대 빈도수 찾기
        long max = frequencyMap.values().stream()
                .mapToLong(Long::longValue)
                .max()
                .orElse(0L);
        
        // 최대 빈도수 중복 확인
        long count = frequencyMap.values().stream()
                .filter(v -> v == max)
                .count();
        
        if (count > 1) {
            System.out.println('?');
        } else {
            frequencyMap.entrySet().stream()
                    .filter(entry -> entry.getValue() == max)
                    .findFirst()
                    .ifPresent(entry -> System.out.println(entry.getKey()));
        }
    }
}
  • 스트림을 안 쓰는게 더 빠르고 직관적이다.

2. 2941번 크로아티아 알파벳

 가. 스트림을 사용하지 않은 경우

import java.io.*;

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

        // 크로아티아 알파벳 리스트
        String[] croatian = { "c=", "c-", "dz=", "d-", "lj", "nj", "s=", "z=" };

        int count = 0;
        for (String alpha : croatian) {
            while (s.contains(alpha)) { // 해당 크로아티아 알파벳이 있는 동안 반복
                s = s.replaceFirst(alpha, " "); // 한 번만 변경
                count++; // 크로아티아 알파벳 개수 증가
            }
        }

        // 공백을 제외한 나머지 문자 개수 추가
        count += s.replace(" ", "").length();

        System.out.println(count);
    }
}
  • 마지막 공백을 제거해 주는 이유는 공백을 제거한 후 남은 문자열도 개수에 포함시켜야 하기 때문이다. 

 

 나. 스트림을 사용 한 경우

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

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

        // 크로아티아 알파벳 리스트
        String[] croatian = { "c=", "c-", "dz=", "d-", "lj", "nj", "s=", "z=" };

        // 크로아티아 알파벳 개수를 먼저 세고, 나머지 문자 개수와 합산
        long count = Arrays.stream(croatian)
                           .mapToLong(alpha -> {
                               long cnt = (s.length() - s.replace(alpha, "").length()) / alpha.length();
                               s = s.replace(alpha, " "); // 이미 카운트한 문자 제거
                               return cnt;
                           }).sum();

        // 남은 문자 개수 추가
        count += s.replace(" ", "").length();
        
        System.out.println(count);
    }
}
  • 나누기를 하는 이유 : 몇 번 반복해서 나왔는지를 확인하기 위해

3. 1316번 그룹 단어 체커

 

  • 입력된 단어를 한 글자씩 확인하면서 처리
  • 연속해서 나온 문자는 그대로 유지, 새로운 문자가 나오면 체크
  • 이미 나왔던 문자가 다시 등장하면 그룹 단어가 아님
  • 모든 단어를 확인하고 그룹 단어의 개수를 출력
import java.io.*;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int N = Integer.parseInt(br.readLine()); // 단어 개수
        int count = 0; // 그룹 단어 개수

        for (int i = 0; i < N; i++) {
            if (isGroupWord(br.readLine())) {
                count++;
            }
        }

        System.out.println(count);
    }

    private static boolean isGroupWord(String word) {
        boolean[] visited = new boolean[26]; // 알파벳 방문 여부 (a~z)
        char prev = ' '; // 이전 문자 초기값 (공백)

        for (char c : word.toCharArray()) { // 문자열을 한 글자씩 검사
            if (c != prev) { // 새로운 문자가 등장했을 때
                if (visited[c - 'a']) return false; // 이미 등장한 문자면 그룹 단어 X
                visited[c - 'a'] = true; // 처음 등장한 문자 체크
                prev = c; // 이전 문자 갱신
            }
        }
        return true; // 그룹 단어임
    }
}

 

예시)

 

문자열 Prev visted 확인 그룹단어여부
a ' ' X (처음 나옴) ✅ 계속 진행
b 'a' X (처음 나옴) ✅ 계속 진행
a 'b' O (다시 나옴) ❌ 그룹 단어 X