-
1213 팰린드롬 만들기백준/그리디 알고리즘 2021. 10. 18. 19:45
https://www.acmicpc.net/problem/1213
1213번: 팰린드롬 만들기
첫째 줄에 문제의 정답을 출력한다. 만약 불가능할 때는 "I'm Sorry Hansoo"를 출력한다. 정답이 여러 개일 경우에는 사전순으로 앞서는 것을 출력한다.
www.acmicpc.net
** 완성본 코드를 보시고 싶으신 분은 아래 <최종 완성본> 코드만 보시면 됩니다!
아이디어 구현(중도 포기)
일단 input[] 배열에 예제 입력된 것을 string으로 담는다.
예시) input = {A,A,B,B,D,D,D,B,B,A,A}
그 다음 ArrayList에 input[] 요소들을 담아서, 그 크기가 유동적으로 변할 수 있게 한다.
(왜냐하면, 중복되는 글자들을 지워나갈 것이므로)
만약 ArrayList[0](=A) 번째 요소랑 ArrayList[2](=A),[3](=B),[4](=B) 요소를 비교해서 같다면
count를 증가시키고 그 요소들을 제거해버린다.
즉, ArrayList[0]=A=ArrayList[1]=ArrayList[9]=ArrayList[10]
count 는 초기에 1로 설정해놨고, 이 경우는 총 count = 4
그리고 이 count는 alphabet이라는 배열에 집어넣는데
alphabet 배열은 알파벳 개수(26) 크기로 만들어서 (alphabet[0]는 A에 대응되고, [1]은 B에 대응되고..)
만약 ArrayList[0]이 A이면 alphabet[0]에다가 그 count값(4)을 입력한다.
그렇게 문자들의 중복 횟수를 alphabet 배열에 계산해서 넣는다.
팰린드롬을 만드려면 글자개수가 짝수개여야 하는데, 단 한 번은 홀수번 가능하다.
그 글자를 팰린드롬 글자의 가운데에 넣으면 상관없기 때문
예를 들어 AABBDDDBBAA 이럴 경우 팰린드롬이 가능하다.
그래서 만약 alphabet 배열 값 중에 홀수개인 경우가 1개라면 위의 경우처럼 괜찮지만
2번 이상이라면 불가능 하므로 I'm Sorry Hansoo 를 출력하게 만든다.
이렇게 하고 나면
alphabet[0]은 A의 개수를 의미하고 alphabet[1]은 B의 개수를 의미한다.
그 후에는 result라는 배열을 만들어서, alphabet[] 배열과 대응시켜서 결과물을 출력한다.
(그런데 또 문자열을 출력할 때 알파벳순서로 출력하라고 했으므로 alphabet[]배열 순서대로 그냥 출력하면 된다.)
AABBDDDBBAA
여기서 볼 수 있듯이 A는 총 4개 이지만, 가운데 글자 D를 중심으로 앞쪽에 A는 2글자, 뒤쪽에도 2글자씩 표현하고 있다.
alphabet[0]은 A의 개수(4)를 의미하는데, 팰린드롬을 만드려면 팰린드롬 글자의 반의 앞쪽에는 (A개수/2)개를 표현하고
뒤쪽에는 또 (A개수/2) 개를 표현해야 하므로,
alphabet[0]/2 만큼만 result[]배열에 A를 집어넣는다.
이렇게 alphabet[25]까지 다 하면 된다.
그런데, 앞에서 말했듯이 한 글자는 홀수개가 가능해서 만약 alphabet[i]가 홀수라면 그 글자는 mid 변수에 하나 빼놓고
그 나머지를 /2 해서 위처럼 result[] 배열에 넣으면 된다.
그러면 result[]배열에 팰린드롬 글자의 반쪽이 완성되게 된다.
즉, AABBD 이만큼.
그리고 mid변수(D)가 있다면 result에 mid변수를 붙인다음 AABBDD,
result[]의 값을 거꾸로 돌려서 또 result[]에 붙여주면 AABBDDDBBAA
팰린드롬 글자가 완성된다.
..이렇게 완성하려고 했으나.. 위의 코드블록에 표시한 --------------** 아래부터 완성이 잘 안된듯 하다
즉, alphabet[]의 글자들을 result[] 글자로 표현하는데부터 막혔다.
그런데 계속 붙잡고 있으면 시간이 너무 많이 소요될 것 같아서 다른 사람의 코드를 참조하기로 했다.
<아래 코드는 위에서 설명했던 내용 관련 코드>
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; public class Main { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String input[]= br.readLine().split(""); ArrayList<String> data = new ArrayList<>(); for(int i=0; i<input.length;i++) { data.add(input[i]); } int alphabet[] = new int [26]; for(int i=0;i<data.size();i++) { String s = data.get(i); int count =1; for(int j=i+1;j<data.size();j++) { if(data.get(j).equals(s)) { count++; data.remove(j); j--; }else { continue; } } int order = (int) s.charAt(0) -65; alphabet[order]=count; } int odd =0; for(int i=0;i<26;i++) { if(alphabet[i]%2==1) { odd++; if(odd==2) { System.out.println("I'm Sorry Hansoo"); } } //--------------** char result[]= new char [50]; char mid; for(int k=0; k<26;k++) { if(alphabet[k]!=0) { if(alphabet[k]%2!=0) { mid=(char)(k+65); } int num = alphabet[k]/2; while(num -->0) { for(int e=0;;e++) { result[k+e]=(char)(k+65); }} } } } } }
<최종 완성본>
아래 참고 자료의 블로그를 참고해서 작성했습니다.
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 input = br.readLine(); int alphabet[] = new int [26]; for(int i=0; i<input.length();i++) { alphabet[input.charAt(i)-65]++; } int count =0; int mid =0; for(int i=0;i<26;i++) { if(alphabet[i]%2!=0) { count++; mid=i; } } if(count>1) { System.out.println("I'm Sorry Hansoo"); return; } StringBuilder make = new StringBuilder(); for(int i =0; i<26;i++) { for(int j=0; j<alphabet[i]/2;j++) { make.append((char)(i+65)); } } StringBuilder result = new StringBuilder(make.toString()); if(count==1) { make.append((char)(mid+65)); } System.out.println(make.toString()+result.reverse()); } }
alphabet[] 배열을 만들어서 입력된 글자들의 글자수를 배열 값으로 넣는다.
즉, AABBC를 입력받았다면
alphabet[0] = 2 (A글자 갯수)
alphabet[1]=2 (B글자 갯수)
alphabet[2]=1 (C글자 갯수)
그 후 alphabet[]배열의 값이 홀수인지 따진다. 그래서 그 경우만큼 count수를 증가시킴
글자수가 홀수인 경우는 한 번은 가능하지만, 두번부터는 불가능하기 때문
(AABBC는 ABCBA으로 가능하지만,
AAACBB는 불가)
그리고 홀수인 경우 한 번은 가능하기 때문에 그 알파벳의 인덱스를 mid변수로 받는다
그 다음 StringBuilder를 이용해서 글자를 만드는데,
i=0일때, j=0이면(입력값이 AABBC라면 j는 alphabet[0]/2=1 즉, j<1이므로 j=0일때만 for문 사용)
그래서 make StringBuilder에다가 (char)(i+65) 즉, 알파벳 A를 붙인다. (1번)
i=1일 때도 마찬가지로 StringBuilder에다가 B를 1개 붙임
i=2일때는 C를 의미하는데, alphabet[2]/2=0이다. 왜냐하면 j가 int형이라서
그래서 얘는 StringBuilder에 붙지 않고
최종적으로 AB가 완성되서 for문을 나옴
그리고 count==1인 경우, 즉 글자 C는 count가 1이라서,
여기서 붙게 됨
즉, StringBuilder에 ABC가 완성됨
이렇게 한 다음 result의 reverse즉, BA를 붙여주면 완성
기억하기 )
for(int j=0; j<alphabet[i]/2;j++) {
이 부분 코드가 너무 마음에 들었다.주의 하기 )
count>=1 인 경우는 글자수가 홀수개인 경우가 1개 이상인 경우인데,
1개일 경우에는 팰린드롬을 만들 수 있지만, 2개부터는 만들 수가 없다.
그래서 count>1 인 경우는 그냥 i'm sorry Hansoo를 출력하고 끝내야 하는데,
코드에서 만약 if (count>1) 부분에서 return; 안 하면
count>1인 경우도 아래 코드(팰린드롬 글자를 만듦)들을 실행하기 때문에 오류가 난다.
참고 자료 :
'백준 > 그리디 알고리즘' 카테고리의 다른 글
10162 전자레인지 (0) 2021.10.18 2309 일곱 난쟁이 * (0) 2021.10.18 1449 수리공 항승 (0) 2021.10.18 1543 문서 검색 (0) 2021.10.18 1789 수들의 합 (0) 2021.10.18