개발자 Saaad

[JAVA] 백준 6단계 (심화 1) 5~8 문제풀이 본문

알고리즘 문제풀이/백준

[JAVA] 백준 6단계 (심화 1) 5~8 문제풀이

Saaad 2025. 1. 23. 23:47

5. 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 str = br.readLine();
        str = str.toUpperCase().trim();

        // 배열을 생성하고 새로운 문자열을 만날 때, 배열에 저장
        // 1개씩 돌면서 문자를 꺼내고, 배열의 인덱스를 증가시키며 카운트 1씩 증가

        // 알파벳 배열
        int[] arr = new int[26];

        // -1로 초기화
        for (int i = 0; i < 26; i++) {
            arr[i] = -1;
        }

        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            int index = c - 'A';

            // 이미 값이 존재하면
            if (arr[index] != -1) {
                arr[index]++;
            } else {
                arr[index] = 1;
            }
        }

        int max = -1; // 초기값 -1
        char ch = '?';
        for (int i = 0; i < 26; i++) {
            if (arr[i] > max) {
                max = arr[i];
                ch = (char)(i + 'A'); 
            } else if (arr[i] == max) { // 갱신된 max값과 같으면 ? 출력
                ch = '?';
            }
        }
        System.out.print(ch);
    }
}
  • 입력받은 문자열을 toUpperCase() 로 대문자로 변환 후 trim()으로 양쪽 공백을 제거한다.
  • 알파벳 배열 arr[] 을 선언하고 값을 -1로 모두 초기화한다.
  • 입력한 문자열의 index번 째 문자를 순서대로 접근하여 char c 에 담는다.
  • c(선택문자)- 'A' 를 하여 index 0 ~ 25까지 알파벳을 할당할 수 있도록 한다.
    아래 아스키코드표를 확인해보면 'A' 는 아스키코드로 65번에 해당한다. 따라서 A~Z 중 문자를 A로 빼면 인덱스화 할 수 있다.
    예를 들면 선택된 문자가 A라면 65 - 65  = 0 으로 index 값은 0이 될 것이고, 'B'는 66- 65기 때문에 index 1이 될 것이다.

  • if문에서 arr[index] 값이 -1이 아니라면 값이 존재하는 상태이기 때문에 개수를 1개 증가시켜주면 된다.
  • else문에 들어왔다면 arr[index] 값이 -1 이었기 때문에 값이 없었던 상태, 즉 최초 그 문자가 등장했기 때문에 값을 1로 저장해주면 된다.
  • max 값과 출력되어야하는 문자 ch를 선언한다.
  • for문에 들어가 max값을 업데이트하고, ch는 'A' 를 더해주고 char로 형변환을 하여 원래 대문자 알파벳이 나올 수 있도록 한다.
  • else if에서는 기존 max값과 arr[index] 값이 일치하면 여러 개의 많이 사용된 알파벳이 존재하는 것이기 때문에 ch에 '?' 을 할당한다.
  • 결과가 출력된다.

6.2941번 크로아티아 알파벳

  • 특정 문자열이 등장할 때마다 개수를 1개씩 증가시킨 값을 출력하면 된다.
  • c= , c- , dz= .. 등 문자열이 나올 때마다 카운팅하면 된다.

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

class Main { 
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        char ch;
        int count = 0;
        String st = br.readLine();
        // ljes=njak
        for(int i=0; i < st.length(); i++){ 
            ch = st.charAt(i);
            if(i < st.length()-1 && ch == 'c'){
                
                if( st.charAt(i+1) == '=') i++;

                else if(st.charAt(i+1) == '-' ) i++;
            }

            else if( i < st.length()-1 && ch == 'd'){

                if(i < st.length()-2 && st.charAt(i+1) == 'z'){
                
                    if(st.charAt(i+2) == '='){
                        i+=2;
                    }
                }

                else if( st.charAt(i+1) == '-'){
                    i++;
                }
            }

            else if(i < st.length()-1 &&  ch == 'l'){
                if(st.charAt(i+1) == 'j') i++;
            }

            else if( i < st.length()-1 && ch == 'n'){
                if( st.charAt(i+1) == 'j') i++;
            }

            else if( i < st.length()-1 && ch == 's'){
                if( st.charAt(i+1) == '=') i++;
            }

            else if( i < st.length()-1 && ch == 'z'){
                if( st.charAt(i+1) == '=') i++;
            }

            count++;
        }
        System.out.print(count);
    }
}
  • 무자비한 if문으로 코드를 풀었다. 
  • 입력받은 문자열을 1개씩 for문을 통해 순회하며 중첩 if문을 통해 해결하였다.

다른 접근법 (String의 contains() ) 

아래는 같이 스터디를 진행하는 팀원이 작성한 코드인데 내 코드보다 낫고 참신한 접근인 것 같아서 소개한다.

import java.io.*;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] croatia = {"c=","c-","dz=","d-","lj","nj","s=","z="};

        String input = br.readLine();

        for (int i = 0; i < croatia.length; i++) {
            if (input.contains(croatia[i])){
                input = input.replace(croatia[i], "H");
            }
        }
        System.out.println(input.length());
    }
}
  • 내 코드와 달리 크로아티아 문자열을 배열에 저장해두었다.
  • 입력받은 문자열에 크로아티아 배열의 값들에 순차적으로 접근하며 각 문자열이 존재하면 기존 문자열을 H로 대체한다.
  •  대체된 문자열의 길이를 출력하면 끝이다.
  • 매우 매우 코드가 간단해진다!!!!

shout out s2ej1n 

아래 링크로 가면 더 자세한 설명이..

https://s2ej1n.tistory.com/103 

 

[백준/Java] 2941 크로아티아 알파벳 / 25206 너의 평점은 (백준 단계별로 풀기 6단계 심화1)

백준 단계별로 풀기 6단계 - 심화1후다닥 간단하게 푼 문제들만 모아보았다.자바8과 자바 11을 통해 풀어보았다.2941 크로아티아 (자바8 68ms / 자바11 104ms)  ✏️ 자바 코드크로아티아 알파벳중 H는

s2ej1n.tistory.com

 

 


7. 1316 그룹 단어 체커

  • 단어 N개를 입력받고 그룹 단어에 해당하는 단어들의 개수를 출력하는 문제이다.
  • 그룹단어란 'aabb' 처럼 각 문자가 연속해서 나타나는 경우만을 이야기한다.
  • 'aba', 'aaabbbcca' 같이 a가 이전에 등장했었다면, a가 또 나오면 이 조건을 위반하게 된다.

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

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

        for (int i = 0; i < num; i++) {
            if (check() == true)
                count++;
        }
        System.out.print(count);
    }

    public static boolean check() throws IOException {// aabbcc
        boolean[] check = new boolean[26];
        int prev = 0;
        String str = br.readLine(); // 문자열 입력

        for (int i = 0; i < str.length(); i++) {
            int now = str.charAt(i); // i번째 문자 저장

            // 앞선 문자와 i번째 문자가 같지 않다면?
            if (prev != now) {

                // 해당문자가 처음 나오는 경우
                if (check[now - 'a'] == false) {
                    check[now - 'a'] = true; // 문자 등장여부 true로 변경
                    prev = now; // 현재 단어를 prev에 저장
                }

                // 해당 문자가 이미 나온 적이 있다면(그룹단어 x)
                else {
                    return false;
                }
            }
        }
        return true;
    }
}
  • check() 메소드를 생성하였다.
  • check() 는 각 입력받은 문자열에 대해서 그룹 단어인지 판별하는 함수이다.
  • prev 변수의 초기값을 0으로 저장하고 now 변수를 이용해 for문에서 차례대로 문자에 접근하게 된다.
  • if(check[now - 'a'] == false 인 경우, 앞에서 check 배열을 초기화해두었기 때문에 해당 문자가 처음 나온 경우가 된다.
    등장 여부를 변경하기 위해 true로 변경하고 prev를 업데이트한다.
  • if(check[now - 'a'] == true 인 경우, 이미 등장했던 문자가 또 등장한 것이다. 그룹단어에 해당하지 않게 되기 때문에
    return false; 를 통해 for문을 종료시킨다.
  • check() 메소드가 종료되면 true 또는 false를 반환하며 main() 에서 count를 증가시키거나 아무것도 하지않게 된다.
  • 그룹 단어의 개수가 출력된다 .

 


8. 25206 너의 평점은

  • 치훈이의 전공학점을 계산하되, P학점은 계산에서 제외하며 계산해야한다.

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

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

       String [] gradeString = {"A+", "A0", "B+", "B0", "C+", "C0", "D+", "D0", "F"};
       double [] grades = {4.5, 4.0, 3.5, 3.0, 2.5, 2.0, 1.5, 1.0 , 0.0};

            
       double scoreSum = 0.0;
       double totalSum = 0.0;

       for (int i = 0; i < 20; i++) {
            StringTokenizer st = new StringTokenizer(br.readLine());
            String subject = st.nextToken();
            double score = Double.parseDouble(st.nextToken());
            String grade = st.nextToken();  // A+ B+.. 

            // 등급이 P면 계산에서 제외
            if(grade.equals("P")) continue;

            scoreSum += score; // 학점의 총합 계산

            for (int j = 0; j < grades.length; j++) {
                if(grade.equals(gradeString[j])) {
                    totalSum += score * grades[j]; // 학점 x 과목평점 (전공평점의 총 합)
                }
            }
       }

       System.out.printf("%.6f",(double)totalSum / scoreSum);
    }
}
  • 과목 평점 (A+, A0 , ... ) 배열 gradeString[]과 같은 순서로 저장되어 있는 학점 배열 grades[] 를 초기화한다.
  • 실수 단위의 계산이기 때문에 double로 변수들(scoreSum, totalSum)을 선언한다.
    scoreSum은 학점의 합을 저장하는 변수이고 totalSum은 각 전공의 (학점 * 과목 평점) 값을 합을 저장하는 변수이다.
  • StringTokenizer 객체 st를 이용해 전공 이름, 점수, 과목 평점을 입력받는다
  • 만약 등급이 P라면 continue를 통해 다음 for문으로 이동한다.
  • 입력받은 점수를 scoreSum에 더해준다 ( 학점의 총합 계산) 
  • for문을 돌며 입력받은 grade( A+, A0 ... ) 와 기존 배열의 값을 비교해 일치하는 인덱스의 위치를 찾아낸다.
  • 해당 인덱스 j 값을 이용해 grades[j] 에 접근하여 과목 평점에 매칭되는 점수를 구하고 totalSum을 업데이트 한다.
  • 원하는 소수점만큼 출력하기 위해 printf()를 사용한다.