일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 프로그래머스
- SWEA
- oracle
- 스택
- 그리디 알고리즘
- 오라클
- 구현
- 완전탐색
- 너비우선탐색
- SW Expert Academy
- 브루트포스
- 문자열
- 그래프 탐색
- DP
- 깊이우선탐색
- 백준 알고리즘
- Python
- 그래프 이론
- BFS
- 백준알고리즘
- 파이썬
- 다익스트라
- 백트래킹
- 데이터베이스
- 자바스크립트
- 너비 우선 탐색
- 다이나믹 프로그래밍
- 브루트포스 알고리즘
- javascript
- DFS
- Today
- Total
민규의 흔적
[Python 파이썬] SWEA 1215번 - [S/W 문제해결 기본] 3일차 - 회문1 본문
2024년 5월 8일
문제 링크 : SWEA 1215번 - [S/W 문제해결 기본] 3일차 - 회문1
문제 접근
8 X 8 사이즈의 글자판에서 회문을 찾는 문제이다.
회문이란, 문자열 뒤집었을 때 원래 문자열과 같은 문자열을 의미하며 예시로는 '기러기', '역삼역', 'ABCBA' 등이 있다.
또한 한 글자 또한 뒤집으면 같은 글자가 되기에 'A', 'Z' 같은 한 글자 또한 회문으로 간주한다.
입력 값으로 찾아야 하는 회문의 길이와 글자판이 주어졌을 때, 길이에 부합하는 회문이 총 몇 개 인지 찾는 문제이다.
단, 회문은 가로 혹은 세로로 이어져있어야 유효하다.(대각선 불가능)
시간 제한이 파이썬 기준 테스트케이스 10개에 30초이며, 글자판의 크기 또한 8 X 8 사이즈이므로 브루트포스 방식을 채택해도 무방하다고 판단했다.
모든 행을 순서대로 탐색하며 각 행에 회문이 있는지 탐색할 것이며, 무작정 특정 길이의 모든 문자열을 조합하여 확인하는 것보다, 다음과 같이 회문의 특성을 이용하여 가지치기를 통해 시간복잡도를 조금이나마 줄여보기로 했다.
다음과 같은 문자열이 회문인지 어떻게 확인할 수 있는가?
길이가 5인 회문을 찾는다고 가정하겠다.
일단 회문은 뒤집어도 같기에,
해당 문자열이 만약 회문이라면 현재 탐색중인 문자열의 시작점 arr[0]과 arr[4]의 요소가 같아야 할 것이다.
만약 다르다면 나머지 요소들을 탐색할 필요 조차 없어지기에 불필요한 연산 생략이 가능하다.
만약 문자열의 시작점과 끝점이 같다면, 양 옆으로 포인트를 한 칸씩 땡겨 탐색을 진행하면 된다.
회문이 맞는지 확인하는 로직이 끝날때까지 유효함을 유지했다면, True를 반환하며 해당 문자열이 회문임을 알 수 있다.
만약 로직 중간에 회문이 아님을 결정났다면, 추가 연산을 생략하고 False를 반환하며 해당 문자열이 회문이 아님을 도출해낸다.
또한, 이 문제는 정해진 길이의 회문을 알아내는 것이기에 다음과 같은 방식으로도 추가 연산을 막을 수 있다.
순서도
1. 찾고자 하는 회문의 길이 length를 입력받고, 8 X 8 사이즈의 글자판 board를 2차원 배열 형태로 입력받는다.
2. 회문의 개수를 담을 cnt를 선언한다.
3. board의 각 행과 열을 모두 탐색하며 각 행과 열에 회문이 존재하는지 판별한다.
3-1. 각 행과 열의 현재 탐색하는 인덱스 값이, 해당 값으로 시작하는 length 길이의 문자열 마지막 값과 같다면 유효성 검사를 수행한다.
3-2. 유효성 검사 결과가 True라면 cnt를 1 증가시킨다.
4. 로직이 종료되면 cnt를 출력한다.
입력 예제
4
CBBCBAAB
CCCBABCB
CAAAACAB
BACCCCAC
AABCBBAC
ACAACABC
BCCBAABC
ABBBCCAA
4
BCBBCACA
BCAAACAC
ABACBCCB
AACBCBCA
ACACBAAA
ACCACCCB
AACAAABA
CACCABCB
...
출력 예제
#1 12
#2 10
...
주의할 점
배열 슬라이싱이 익숙하고 회문의 특성을 이해했다면 조건문 작성에 크게 어려움이 없었을 것이라 생각한다.
전체 코드
def isValid(arr):
i = 1
while i < length // 2:
if arr[i] != arr[length - i - 1]:
return False
i += 1
return True
def solution():
cnt = 0
# 각 행 탐색
for row in range(8):
for col in range(8 - length + 1):
if board[row][col] == board[row][col + length - 1]:
temp = board[row][col : col + length]
if isValid(temp):
cnt += 1
# 각 열 탐색
for col in range(8):
for row in range(8 - length + 1):
if board[row][col] == board[row + length - 1][col]:
temp = []
for i in range(row, row + length):
temp.append(board[i][col])
if isValid(temp):
cnt += 1
return cnt
T = 10
for test_case in range(1, T + 1):
length = int(input())
board = []
for _ in range(8):
board.append(list(input()))
print(f'#{test_case} {solution()}')
풀이 후기
브루트포스 방식으로 풀었고 나름 가지치기 로직도 추가하였으나, 더 효율적인 코드가 분명 있을 것이라 생각된다.
'SWEA' 카테고리의 다른 글
[Python 파이썬] SWEA 11315번 - 오목 판정 (0) | 2024.05.14 |
---|---|
[Python 파이썬] SWEA 1860번 - 진기의 최고급 붕어빵 (0) | 2024.05.10 |
[Python 파이썬] SWEA 1216번 - [S/W 문제해결 기본] 3일차 - 회문2 (0) | 2024.05.10 |
Python 파이썬] SWEA 1220번 - [S/W 문제해결 기본] 5일차 - Magnetic (0) | 2024.05.08 |
[Python 파이썬] SWEA 1289번 - 원재의 메모리 복구하기 (0) | 2024.05.08 |