[백준 9046]
https://www.acmicpc.net/problem/9046

입력문 중 가장 빈도가 높은 알파벳을 찾고 복호화 과정을 거친 알파벳을 출력하는 문제이다.
문제를 풀기 전 간단하게 알고리즘에 대해 끄적여봤다.

가장 처음으로 한 일은 복호화를 위해 평문과 암호문을 ArrayList에 저장하기로 했다.
// 암호화 문자열
String substitution_temp = "wghuvijxpqrstacdebfklmnoyz";
// 평소 문자열
String original_temp = "abcdefghijklmnopqrstuvwxyz";
// 문자열 to ArrayList
char[] substitution = new char[substitution_temp.length()];
char[] original = new char[original_temp.length()];
for (int i = 0; i < substitution.length; i++) {
substitution[i] = substitution_temp.charAt(i);
original[i] = original_temp.charAt(i);
}
처음부터 문자열을 배열이나 ArrayList에 넣지 않고 변환한 이유는 {'a', 'b', 'c'} 이런식으로 따옴표로 나눠서 배열을 선언하기 귀찮았기 때문이다.
count, request : 사용자의 입력을 저장
number : 빈도수를 기록하기 위한 배열
max_index : 가장 높은 빈도수를 가진 인덱스 값을 저장할 배열
det : 가장 높은 빈도수의 값이 여러 개일 경우 판별하기 위한 boolean 변수
작성한 코드는 아래와 같다.
int count = sc.nextInt();
sc.nextLine();
for(int j = 0; j < count; j++) {
// a ~ z 크기의 배열 생성 -> 빈도 표기
int[] number = new int[26];
int max_index = 0; // 높은 빈도의 알파벳 인덱스를 저장(초기 0)
boolean det = true; // 빈도 동일 시 false로 변경
String request = sc.nextLine();
for (int k = 0; k < request.length(); k++) {
char ch = request.charAt(k);
if (Character.isLetter(ch)) { // 공백 처리
number[ch - 'a']++; // 해당 알파벳의 인덱스 값을 계산하여 배열에 저장
}
}
공백을 처리하기 위해.charAt 메서드를 사용하였다.
해당 메서드는 사용 방법을 몰라 구글링을 사용하였다...
그렇게 공백을 제거한 문자는 알파벳의 인덱스를 계산하여 배열에 빈도수를 증가시킨다.
// 최빈 알파벳 구하기
for (int r = 1; r < number.length; r++) {
// max_index를 변경하며 true로 처리한다.
if (number[r] > number[max_index]) {
max_index = r;
det = true;
}
// 동일한 값의 경우에는 false로 변경한다.
else if (number[r] == number[max_index]) {
det = false;
}
}
// det 여부에 따라 출력을 달리한다.
if(det == true) {
System.out.println(original[max_index]);
}
else {
System.out.println("?");
}
max_index 변수를 1로 선언하였으니 1번째 인덱스부터 순회하도록 한다.
그렇게 만약 순회 중 더 큰 값을 발견하면 max_index를 업데이트 하며 boolean을 true로 유지 / 변경 한다.
만약 동일한 값의 경우에는 false로 변경한다.
이제 해당 boolean에 따라 조건을 나누어 정답을 출력하였다.
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 암호화 문자
//String substitution_temp = "wghuvijxpqrstacdebfklmnoyz";
// 평소 문자
String original_temp = "abcdefghijklmnopqrstuvwxyz";
// 배열 to ArrayList
//char[] substitution = new char[substitution_temp.length()];
char[] original = new char[original_temp.length()];
for (int i = 0; i < original.length; i++) {
//substitution[i] = substitution_temp.charAt(i);
original[i] = original_temp.charAt(i);
}
int count = sc.nextInt();
sc.nextLine();
for(int j = 0; j < count; j++) {
// a ~ z 크기의 배열 생성 -> 빈도 표기
int[] number = new int[26];
int max_index = 0; // 높은 빈도의 알파벳 인덱스를 저장(초기 0)
boolean det = true; // 빈도 동일 시 false로 변경
String request = sc.nextLine();
for (int k = 0; k < request.length(); k++) {
char ch = request.charAt(k);
if (Character.isLetter(ch)) { // 공백 처리
number[ch - 'a']++; // 해당 알파벳의 인덱스 값을 계산하여 배열에 저장
}
}
// 최빈 알파벳 구하기
for (int r = 1; r < number.length; r++) {
// max_index를 변경하며 true로 처리한다.
if (number[r] > number[max_index]) {
max_index = r;
det = true;
}
// 동일한 값의 경우에는 false로 변경한다.
else if (number[r] == number[max_index]) {
det = false;
}
}
// det 여부에 따라 출력을 달리한다.
if(det == true) {
System.out.println(original[max_index]);
}
else {
System.out.println("?");
}
}
}
}

깃허브에 푸시 후 PR까지 모두 완료한 이후 깨닫게 된 점이 있다.
해당 코드는 문제는 없지만 상당히 비효율적으로 작성되어 있다.
처음 암호화 된 문자가 저장된 substitution 배열은 코드에서 사용되지 않는다.
또한, 시간복잡도가 O(n^2) 이므로 상당히 비효율적인 코드이다.
정답이긴 하나 코드를 정말 비효율적으로 작성한 것 같아 많은 수정이 필요해 보인다.
추후에 다시 수정해서 올려야겠다.
그리고 깃허브 리포지토리에 단순히 커밋 푸시를 통해 올리면 되는 줄 알았지만 포크와 PR을 사용해서 올려야 하는 규칙이 존재했기에 해당 규칙을 따라야 했다.
그렇게 fork, clone, PR 까지 다양한 시행착오를 거쳐 해냈지만 이게 맞게 잘 적용된 건지는 잘 모르겠다..ㅠ
끗.
암호화된 문자를 복호화하라는 내용은 문제에 없어서 배열을 따로 만들지 않아도 될 거 같아요~
그리고 크롬에서 제공하는 백준 허브 사용하면 깃허브에 자동 푸시해주니까 찾아보시면 좋을 것 같아요!
좋은 글 잘 보고 갑니다 :)