꾸물꾸물 졔의 개발공부

[백준] 17609 회문 - JAVA 본문

알고리즘/백준

[백준] 17609 회문 - JAVA

체제 2023. 8. 25. 17:19

https://www.acmicpc.net/problem/17609

 

17609번: 회문

각 문자열이 회문인지, 유사 회문인지, 둘 모두 해당되지 않는지를 판단하여 회문이면 0, 유사 회문이면 1, 둘 모두 아니면 2를 순서대로 한 줄에 하나씩 출력한다.

www.acmicpc.net

 

 

[알고리즘]

  • 투 포인터
  • 제일 앞/뒤 양끝에서 두개의 포인터가 중간으로 오면서 투 포인터가 가리키는 값이 동일한지 확인 
  • 만약 다른 값이 나온다면 하나씩 제외하고 회문인지 확인하여 회문/유사회문/일반 판별 

 

[설계]

  • 양 끝을 가리키는 포인터로 시작 (left /right) 
  • 만약 left, right 가 가리키는 값이 같을 경우 left와 right를 가운데쪽으로 이동
  • left, right가 가리키는 값이 다를 경우 
    1. left가 가리키는 문자를 제외하고 회문인지 확인 
    2. right가 가리키는 문자를 제외하고 회문인지 확인
    3. 둘 중 하나라도 회문이라면 "유사회문", 그렇지 않다면 "일반 문자열"
💡예를 들어, xyyyyxy 라는 문자열이 입력으로 주어졌다고 가정해보자. left ='x' , right='y'로 투 포인터가 가리키는 값이 다르다. 
   1. left 가 가리키는 문자를 제외하고 yyyyxy 가 회문인지 확인 >회문 아님 
   2. right 가 가리키는 문자를 제외하고 xyyyyx 가 회문인지 확인 > 회문
즉, "유사회문" 

 

 

[구현 과정]

 

1. check() : 주어진 문자열을 투 포인터로 탐색하며 회문인지 확인하는 함수

- 처음 투포인터는 양 끝 (left / right) 으로 하여 시작한다. 
- left < right 일 동안 아래 과정을 반복한다. (같거나 left 가 커지면 종료) 
- 투 포인터가 가리키는 값이 같을 경우 : 다음 문자를 탐색하기 위해 중간으로 모인다. (left ++, right--) 
- 투 포인터가 가리키는 값이 다를 경우 : 유사회문인지 확인
   1. left가 가리키는 문자를 제외하고 회문인지 확인. checkSec (left+1, right)
   2. right가 가리키는 문자를 제외하고 회문인지 확인. checkSec (left, right-1)  
- (1,2) 중 하나라도 회문이 존재한다면 해당 문자열은 "유사회문" 이므로 1 반환 
- 그렇지 않다면 "일반문자열" 2 반환 
- while 문이 무사히 종료되었다면 "회문" 0 반환 

 

2. checkSec() : check() 함수에서 문자를 하나씩 제외한 (서브)문자열이 회문인지 확인 (투 포인터 로직은 동일)

- 양 끝을 투 포인터로 하여 가리키는 값이 동일한지 확인 
- left < right 일 동안 아래 과정을 반복한다. (같거나 left 가 커지면 종료) 
- 투 포인터가 가리키는 값이 같을 경우 : 다음 문자를 탐색하기 위해 중간으로 모인다. (left ++, right--) 
- 투 포인터가 가리키는 값이 다를 경우 : 회문이 아니므로 false 반환 
- while 문이 무사히 종료되었다면 true 반환 (=회문) 

 


 

[소스 코드]

import java.io.*;

public class Main {
	public static void main(String[] args) throws Exception{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 
		
		int T= Integer.parseInt(br.readLine()); 
		while(T-- >0) {
			String s= br.readLine(); 
			int res= check(s, 0, s.length()-1); 
			System.out.println(res);
		}
		
	}//end of main
	
	/*
	 * 0:화문 
	 * 1:유사화문
	 * 2:그 외/
	 */
	private static int check(String s, int left, int right) {
		while(left<right) {
			
			if(s.charAt(left)==s.charAt(right)) {
				left++;
				right--; 
			}
			
			//만약 다를 경우 ,
			else {
				//왼쪽 하나 제외/ 오른쪽 하나 제외하고 회문인지 확인 
				boolean res1 = checkSec(s, left+1, right);
				boolean res2 = checkSec(s, left, right-1); 
                
				//둘중 하나라도 회문이라면, 유사회문
				if(res1 || res2) return 1;
				
				return 2;
			}
		}
		return 0;
	}
    
	private static boolean checkSec (String s, int left, int right) {
		while(left< right) {
			if(s.charAt(left) == s.charAt(right)) {
				left++;
				right--; 
				continue; 
			}
			return false; 
		}
		return true; 
	}
}//end of class

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

[백준] 1806 부분합 - JAVA  (0) 2023.08.30
[백준] 2638 치즈 - JAVA  (0) 2023.08.29
[백준] 1253 좋다 - JAVA  (1) 2023.08.24
[백준] 2665 미로만들기 - JAVA  (1) 2023.08.23
[백준] 1261 알고스팟 - JAVA  (0) 2023.08.22