Home [알고리즘] 유효한 팰린드롬
Post
Cancel

[알고리즘] 유효한 팰린드롬

문제

주어진 문자열이 팰린드롬인지 확인하라. 대소문자를 구분하지 않으며. 영문자와 숫자만을 대상으로 한다.

입력

1
"A man, a plan, a canal: Panama"

출력

1
true

팰린드롬(Palindrome)이란?


앞뒤가 똑같은 단어나 문장으로, 뒤집어도 같은 말이 되는 단어 또는 문장을 팰린드롬(Palindrome)이라고 한다.

풀이1


먼저 문자열을 입력받고, 이 문자열 중, 문자인 것만 따로 배열에 추가한다. 문자인것을 판별하는 isalnum() 함수를 사용하고, 대소문자를 구분하지 않으므로 입력받은 문자열을 모두 lower()로 소문자로 변환하고 리스트에 추가한다.

1
2
3
4
strs = []
for char in s: # s는 입력받은 문자열
	if char.isalnum():
		strs.append(char.lower())

위의 코드로 입력값을 받은 후 strs을 print()로 출력하게 되면 arr에 담긴 리스트를 다음과 같이 확인할 수 있다.

1
['a', 'm', 'a', 'n', 'a', 'p', 'l', 'a', 'n', 'a', 'c', 'a', 'n', 'a', 'l', 'p', 'a', 'n', 'a', 'm', 'a']

이 후 펠린드롬 여부를 다음과 같이 판별한다.

1
2
3
4
while len(arr) > 1:
	if arr.pop(0) != arr.pop():
			return False
return True

파이썬 리스트의 함수인 pop(0)이용하여 맨앞의 값과 pop()을 이용하여 마지막 값을 매칭하가면서 만약 일치하지 않은 경우, 펠린드롬이 아니라고 판단하여 False를 반한한다. 만약 while문을 모두 수행했다면 True를 반환한다.

전체 코드는 아래와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
def isPalindrome(self, s: str) -> bool:
    strs = []
    for char in s:
        if char.isalnum():
            arrstrsappend(char.lower())

    # 팰린드롬 여부 판별
    while len(strs) > 1:
        if strs.pop(0) != strs.pop():
            return False

    return True
    

풀이 2 (deque 자료형을 이용한 풀이)


위의 풀이1처럼 pop(0)연산을 사용하게 되면 첫 번째 값을 꺼내고, 그 안에서 재정렬이 일어나기 때문에 시간복잡도가 O(n)이 되게 된다. 이 연산 시간을 줄이기 위해 deque의 popleft()를 사용하여 해결할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from collections import deque

def isPalindrome(self, s: str) -> bool:
    # 자료형 데크로 선언
    strs: Deque = collections.deque()

    for char in s:
        if char.isalnum():
            strs.append(char.lower())

    while len(strs) > 1:
        if strs.popleft() != strs.pop():
            return False

    return True

풀이 1처럼 리스트를 이용해 구현하고, n번씩 반복하면 시간 복잡도가 O(n^2)이 나오게 되지만, deque를 이용해 구현하게 되면 O(n)으로 성능이 개선되는것을 볼 수 있다.

풀이 3 (슬라이싱 사용)


슬라이싱을 이용하여 문제를 풀면 코드는 다음과 같다.

1
2
3
4
5
6
7
8
import re

def isPalindrome(self, s: str) -> bool:
    s = s.lower()
    # 정규식으로 불필요한 문자 필터링
    s = re.sub('[^a-z0-9]', '', s)

    return s == s[::-1]  # 슬라이싱

s = re.sub('[^a-z0-9]', '', s)를 이용해 정규식으로 불필요한 문자를 필터링 한다음, 파이썬의 슬라싱을 이용하여 앞뒤가 똑같은 문자열인지 판별할 수 있다. 파이썬의 슬라이싱에서 [::-1]을 이용하여 리스트를 뒤집을 수 있다.

정리


유효한 펠린드롬 문제를 3가지 풀이 방법으로 알아보았다. 3가지 풀이 방법 중에서 풀이 3인 슬라이싱을 이용한 풀이 방법이 가장 빠르게 실행되었으며, 슬라이싱을 사용하면 내부적으로 C로 빠르게 구현되어있어 훨씬 더 좋은 속도를 보여주었다.