ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 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인 경우도 아래 코드(팰린드롬 글자를 만듦)들을 실행하기 때문에 오류가 난다. 

     

    참고 자료 : 

    https://broship.tistory.com/134?category=845145 

    '백준 > 그리디 알고리즘' 카테고리의 다른 글

    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

    댓글

Designed by Tistory.