LeetCode/NeetCode

[Two Pointers] 125. Valid Palindrome

hyunkookim 2024. 11. 28. 17:23

125. Valid Palindrome

 

내 코드

 

class Solution:
    def isPalindrome(self, s: str) -> bool:
        """
        isalnum은 **"is alphabetic or numeric"**의 약자로, 
        알파벳 또는 숫자인지 확인하는 메서드입니다.
        - is: "인지 확인"을 의미 (True/False 결과 반환).
        - al: alphabetic(알파벳)의 약자.
        - num: numeric(숫자)의 약자.
        숫자 이거나 알파벳이면 True

        isdigit(): 숫자인지 확인
        """

        only_alnum = ""
        for w in s:
            if w.isalnum():
                if w.isdigit():
                    only_alnum += w
                else:
                    only_alnum += w.lower()
        return only_alnum == only_alnum[::-1]

 

https://youtu.be/jJXJ16kPFWg?si=MAYq3FrIYDVxobEH

 

 

class Solution:
    # 주어진 문자 c가 알파벳(A-Z, a-z) 또는 숫자(0-9)인지 확인하는 함수
    def alphaNum(self, c):
        return (ord('A') <= ord(c) <= ord('Z') or  # 대문자 여부 확인
                ord('a') <= ord(c) <= ord('z') or  # 소문자 여부 확인
                ord('0') <= ord(c) <= ord('9'))    # 숫자 여부 확인

    # 문자열 s가 팰린드롬인지 확인하는 함수
    def isPalindrome(self, s: str) -> bool:
        # 두 포인터를 문자열의 시작(l)과 끝(r)에 초기화
        l, r = 0, len(s) - 1

        # 포인터가 서로 만나기 전까지 반복
        while l < r:
            # 왼쪽 포인터가 가리키는 문자가 알파벳/숫자가 아니면 포인터 이동
            while l < r and not self.alphaNum(s[l]):
                l += 1  # 왼쪽 포인터를 오른쪽으로 이동
            # 오른쪽 포인터가 가리키는 문자가 알파벳/숫자가 아니면 포인터 이동
            while l < r and not self.alphaNum(s[r]):
                r -= 1  # 오른쪽 포인터를 왼쪽으로 이동

            # 대소문자를 무시하고 현재 포인터의 문자가 다르면 팰린드롬이 아님
            if s[l].lower() != s[r].lower():
                return False  # 팰린드롬이 아니므로 False 반환

            # 양쪽 포인터를 한 칸씩 이동
            l, r = l + 1, r - 1

        # 모든 문자가 일치하면 팰린드롬임
        return True

 

최종 코드

"""
        A palindrome is a string that reads the same forward and backward. 
        It is also case-insensitive and ignores all non-alphanumeric characters.
        팰린드롬은 앞뒤로 읽어도 같은 문자열입니다. 
        대소문자 상관없이, 알파벳과 숫자만 사용해서~

        case-insensitive → 대소문자를 구분하지 않는다
            예: "A"와 "a"를 같은 문자로 본다.
        ignores all non-alphanumeric characters → 알파벳과 숫자가 아닌 문자는 무시한다
            예: 공백( ), 쉼표(,), 마침표(.), 느낌표(!), 콜론(:), 슬래시(/) 같은 것들을 제외한다        
        """
        alphachar = 'abcdefghijklnmopqrstuvwxyz0123456789'
        
        s = s.lower() 
        newSarr = [s[i] for i in range(len(s)) if s[i] in alphachar]  
        print(newSarr)
        newS = "".join(newSarr)
        print(newS)

        if newS == newS[::-1]:
            return True
        return False
        # for j in range(len(newS)//2):
        #     if newS[j] != newS[len(newS)-j-1]:
        #         return False
        
        return True

 

"""
        A palindrome is a string that reads the same forward and backward. 
        It is also case-insensitive and ignores all non-alphanumeric characters.
        팰린드롬은 앞뒤로 읽어도 같은 문자열입니다. 
        대소문자 상관없이, 알파벳과 숫자만 사용해서~

        case-insensitive → 대소문자를 구분하지 않는다
            예: "A"와 "a"를 같은 문자로 본다.
        ignores all non-alphanumeric characters → 알파벳과 숫자가 아닌 문자는 무시한다
            예: 공백( ), 쉼표(,), 마침표(.), 느낌표(!), 콜론(:), 슬래시(/) 같은 것들을 제외한다        
        """
        alphachar = 'abcdefghijklnmopqrstuvwxyz0123456789'
        
        s = s.lower() 
        newSarr = [s[i] for i in range(len(s)) if s[i] in alphachar]  
        print(newSarr)
        newS = "".join(newSarr)
        print(newS)

        # if newS == newS[::-1]:
        #     return True
        # return False
        for j in range(len(newS)//2):
            if newS[j] != newS[len(newS)-j-1]:
                return False
        
        return True

 

이 문제는 투 포인터(Two Pointers) 기법으로도 깔끔하게 풀 수 있어요.
대소문자 구분 없이, 알파벳과 숫자만 비교하면서 앞뒤에서 좁혀오는 방식이에요.


✅ 투 포인터 풀이 (한글 주석 포함):

class Solution:
    def isPalindrome(self, s: str) -> bool:
        l, r = 0, len(s) - 1  # 왼쪽과 오른쪽 포인터 초기화

        while l < r:
            # 왼쪽 포인터가 알파벳/숫자가 아니면 건너뛰기
            if not s[l].isalnum():
                l += 1
                continue

            # 오른쪽 포인터가 알파벳/숫자가 아니면 건너뛰기
            if not s[r].isalnum():
                r -= 1
                continue

            # 소문자로 바꿔서 비교 (대소문자 무시)
            if s[l].lower() != s[r].lower():
                return False  # 다르면 회문 아님

            # 같으면 포인터 이동
            l += 1
            r -= 1

        return True  # 끝까지 통과하면 회문