LeetCode/Grind169

409. Longest Palindrome ★

hyunkookim 2025. 4. 22. 07:55

 

409. Longest Palindrome

class Solution:
    def longestPalindrome(self, s: str) -> int:
        # s 는 대소문자 모두 가능
        # s 의 문자로 만들수 있는, 최고로 긴 Palindrome 길이 반환
        # Palindrome 은 앞으로 읽으나 뒤로 읽으나 같은 문자
        # 글자 단위로 count 한뒤 2로 나누고. 1개짜리 문자 있으면 1 더할수 있음
        countDict = {}
        for w in s:
            if w not in countDict:
                countDict[w] = 0
            countDict[w] += 1

        if len(countDict) == 1: # 한문자로 되어있으니 온전히 Palindrome 임
            return len(s)

        Len_wo1 = 0
        isCnt1 = 0
        for k, v in countDict.items():
            Len_wo1 += v//2
            if v == 1 or v%2 == 1: # 홀수개 이더라도.. 이게 중간에 올수있음..
              isCnt1 = 1
        return Len_wo1*2 +  isCnt1

 

오! 아주 잘 푸셨어요! 🎯 핵심 아이디어도 정확히 잡으셨고, 직접 구현도 잘 하셨어요.
다만, 몇 군데 리팩터링하면 더 깔끔하고 효율적인 코드가 될 수 있어요.


✅ 코드 구조 피드백

1. if len(countDict) == 1: 부분은 사실 불필요합니다.

  • 전체 반복 로직이 이미 홀/짝 처리를 잘 하고 있어서 이 조건 없이도 정답이 나옵니다.
  • 이건 "최적화"가 아니라 "예외처리"인데, 없어도 되고 깔끔해집니다.

2. 변수 이름은 조금만 더 직관적으로!

  • Len_wo1 → half_sum or even_part
  • isCnt1 → has_odd (중간에 올 수 있는 홀수 문자가 있는지)

3. v == 1 or v % 2 == 1은 v % 2 == 1로 충분해요.


✨ 리팩터링된 코드 (같은 로직, 더 깔끔)

class Solution:
    def longestPalindrome(self, s: str) -> int:
        countDict = {}
        for ch in s:
            countDict[ch] = countDict.get(ch, 0) + 1

        length = 0
        has_odd = 0

        for v in countDict.values():
            length += (v // 2) * 2  # 짝수 개수만 합산
            if v % 2 == 1:
                has_odd = 1  # 홀수 개 하나는 가운데 올 수 있음

        return length + has_odd

🧠 로직 요약

  • 모든 문자의 개수 중 짝수 개수는 그대로 양쪽에 배치 가능 → v // 2 * 2
  • 홀수 개 있는 문자 중 하나는 가운데에 배치 가능 → +1
항목 복잡도
시간복잡도 O(N) (N은 문자열 길이)
공간복잡도 O(1) (영문 알파벳 수는 고정)