LeetCode - The World's Leading Online Programming Learning Platform

Problem

  1. input: 문자 s
  2. output: 주어진 문자에서 최장 길이의 팰린드롬 리턴

Idea

모든 Substring에 대해 팰린드롬인지 확인하여 최장길이를 찾고자 했다.

팰린드롬인지 확인하는 방법은 2가지

  1. 시작idx, 끝idx에서 중앙으로 좁혀오며 비교하는 방식 → 끝 idx를 알아야함(길이가 고정)
  2. 중앙에서부터 양끝으로 넓혀가며 비교하는 방식 → 중앙 idx를 알아야함(계속 같다면 무한 확장)

1, 2의 방법으로 모두 풀이를 해본 결과, 1의 방법은 확인하고자 하는 길이가 고정되어 있으므로 해당 문제에서는 2번이 더 적합하다.

Solution

  1. BruteForce ⭕

    가능한 모든 시작점에서, 모든 길이에 대해 팰린드롬인지 확인

    class Solution {
        fun longestPalindrome(s: String): String {
            for (len in s.length downTo 1) {
                for (start in 0..s.length-len) {
                    val palindrome = s.substring(start, start + len)
                    if (isPalindrome(palindrome)) return palindrome
                }
            }
            return ""
        }
    }
    // 주어진 문자가 팰린드롬인지 판단
    fun isPalindrome(s: String): Boolean {
        var left = 0
        var right = s.length-1
        // 양끝에서 투 포인터 탐색
        while (s[left] == s[right] && left < right) {
            left++
            right--
        }
        return (left >= right)
    }
    

    시간 복잡도: 문자 순회(시작점) X 가능한 길이 X 팰린드롬 판단 = n^3

    Untitled

  2. 모든 idx를 팰린드롬의 중앙으로 두고, 최장길이 비교 1에서는 시작점을 기준으로 특정 길이로 문자를 슬리이싱한 후, 해당 문자가 팰린드롬인지 판단(양끝 → 중간 투포인터 탐색)했음 ⇒ 중복되는 탐색 존재

    → 팰린드롬은 중간 기준을 중심으로 좌우 대칭

    → 팰린드롬 판단에 투포인터 탐색 사용

    → 탐색 시작점을 팰린드롬의 중간점으로 두고 최장 길이 구하기(중간 → 양끝 투포인터 탐색)로 탐색을 한번 줄일 수 있음

    class Solution {
        fun longestPalindrome(s: String): String {
            var answer = ""
            for (i in s.indices) {
                val l1 = isPalindrome(i, i, s) // 가운데 값이 있는 경우 -> 전체 길이 홀수
                val l2 = isPalindrome(i, i+1, s) // 가운데 값이 없는 경우 -> 전체 길이 짝수
                if (l1 >= l2 && l1 > answer.length) {
                    answer = s.substring(i - (l1/2), i + (l1/2) + 1)
                } else if (l1 < l2 && l2 > answer.length) {
                    answer = s.substring(i - (l2/2) + 1, i + (l2/2) + 1)
                }
            }
            return answer
        }
    
    		// 주어진 문자열[s:e]에서 가장 긴 팰린드롬의 길이 리턴
        fun isPalindrome(s: Int, e: Int, str: String): Int {
            var left = s
            var right = e
            var len = 0
            // 시작지점에서 양 끝으로 투 포인터 탐색
            while (left >= 0 && right < str.length && str[left] == str[right]) {
                len = right - left + 1
                left--
                right++
            }
            return len
        }
    }
    

    시간 복잡도: 문자 순회(시작점) X 팰린드롬 최장길이 탐색 = n^2

    Untitled

Point

  1. 1의 방법에서 중복되는 탐색

    a b c b a

  2. 팰린드롬 판단은 중간점을 기준으로 양끝으로 투포인터 탐색하는 습관 가질 것

    위의 1번 풀이도 Visited를 사용하여 이미 확인한 인덱스 범위를 저장하면 2번과 동일한 성능을 보여줄 수 있다. 하지만 2의 방식이 훨씬 직관적이고 단순하다.