이번 문제는 팰린드롬에 대해서 풀어보겠습니다.
팰린드롬은 데칼코마니 형태의 숫자나 문자를 나타내는 문제로 유형은 크게
입력된 내용이 팰린드롬인지 여부와 입력된 내용을 팰린드롬으로 만드는 방법
이렇게 두 가지입니다.
이번 포스팅에서는 팰린드롬인지 여부를 파악하는 방법으로 DP 방식을 활용하여 풀겠습니다.
푸는 방식은 Bottom-Up 방식을 사용해서 풀겠습니다.
사실 Top-Down 방식이 더 간단하고 쉽긴 하지만, 개인적으로 이번 문제는 Bottom-Up 방식이 더 어렵고
Bottom-Up 방식을 안다면 Top-Down 도 쉽게 풀 수 있을 것이라 생각하여 결정하였습니다.
우선 점화식부터 세워보면 D[i][j]는 i부터 시작해서 j까지의 숫자 중 팰린드롬이 맞는지 여부를 파악한다고
정의할 수 있습니다.
점화식을 세울 때 나올 수 있는 경우의 수는 크게 3가지입니다.
첫 번째로는 시작점과 종료점이 같을 경우입니다.
i == j일 경우는 반드시 팰린드롬이어야만 합니다.
가령 3이라는 숫자를 볼 때 처음 시작할 때도 3이고 마지막도 3이기 때문에
팰린드롬이라고 말할 수 있습니다.
두 번째로는 시작점과 종료점이 하나 차이일 경우입니다.
i+1 == j 일 경우 해당 위치의 값 A[i]와 A[j]가 같을 경우 d[i][j]는 팰린드롬이라고 표현할 수 있습니다.
마지막으로는 시작점과 종료점이 둘 이상 차이날 경우입니다.
i+k == j 일 때이며, 팰린드롬이 성립하기 위해서는 시작점에서의 값 A[i]와
종료점에서의 값 A[j]이 같아야 합니다.
그리고 d[i][j]가 팰린드롬이기 위해서는 앞서 발생하는 d[i+1][j-1]인 경우도 팰린드롬이어야 하므로
이 두 조건을 모두 체크한 뒤에 d[i][j] = '팰린드롬' 이라고 정의할 수 있습니다.
따라서 코드는 다음과 같습니다.
* 선언부 *
private static Scanner scanner;
private static boolean[][] d; // 팰린드롬 여부를 파악
private static int[] a; // 해당 위치에 들어갈 값
* 구현부 *
scanner = new Scanner(System.in);
int n = scanner.nextInt();
a = new int[n + 1];
for (int i = 1; i <= n; i++)
a[i] = scanner.nextInt();
d = new boolean[n + 1][n + 1];
for (int i = 1; i <= n; i++) {
d[i][i] = true;
}
// --> 시작점과 종료점이 같을 경우 모두 팰린드롬!
for (int i = 1; i < n; i++) {
if (a[i] == a[i + 1])
d[i][i + 1] = true;
}
// --> 시작점과 종료점이 길이 하나 차이 날 경우 그 값이 같은지 체크 한 뒤 같으면 팰린드롬이라고 정의
for (int k = 2; k <= n; k++) {
for (int i = 1; i <= n - k; i++) {
int j = k + i;
if (a[i] == a[j] && d[i + 1][j - 1]) {
d[i][j] = true;
}
}
}
// 시작점과 종료점의 길이가 2이상 날 경우이므로 k가 2부터 시작하게 됩니다. 길이 차이는 최대 n까지
// 발생할 수 있으며 j값은 시작점과 시작점으로부터 종료점까지의 길이의 합입니다.
// 다음 두 반복문을 설정한 뒤 기존 조건대로 시작점과 종료점에서의 값을 비교합니다.
// 이 두 값이 같아야하며 동시에 이 전 경우도 팰린드롬이어야 합니다.
// 두 조건이 모두 성립할 경우 현재 i의 시작점에서 j의 종료점까지인 경우도
// 팰린드롬이라고 정의할 수 있습니다.
전체 코드는 다음과 같습니다.
import java.util.Scanner;
public class 팰린드롬_2 {
private static Scanner scanner;
private static boolean[][] d;
private static int[] a;
public static void main(String[] args) {
// TODO Auto-generated method stub
scanner = new Scanner(System.in);
int n = scanner.nextInt();
// a 갯수
a = new int[n + 1];
for (int i = 1; i <= n; i++)
a[i] = scanner.nextInt();
d = new boolean[n + 1][n + 1];
for (int i = 1; i <= n; i++) {
d[i][i] = true;
}
for (int i = 1; i < n; i++) {
if (a[i] == a[i + 1])
d[i][i + 1] = true;
}
for (int k = 2; k <= n; k++) {
for (int i = 1; i <= n - k; i++) {
int j = k + i;
if (a[i] == a[j] && d[i + 1][j - 1]) {
d[i][j] = true;
}
}
}
int t = scanner.nextInt();
// test case
while (t-- > 0) {
int s = scanner.nextInt();
int e = scanner.nextInt();
if (d[s][e]) {
System.out.println(1);
} else {
System.out.println(0);
}
}
}
}
감사합니다.
'Algorithm' 카테고리의 다른 글
BOJ_11066_파일합치기 (0) | 2018.07.29 |
---|---|
팰린드롬 만들기 (0) | 2018.07.27 |
BOJ_2294_동전2 (0) | 2018.07.27 |
BOJ_1로만들기_1463 (0) | 2018.07.20 |
포도주 시식 BOJ_2156 (0) | 2018.07.09 |