-
2021-01-19] Longest Palindromic SubstringIT/자기계발 ( Leetcode ) 2021. 1. 19. 23:07반응형
오늘의 문제:
Explore - LeetCode
LeetCode Explore is the best place for everyone to start practicing and learning on LeetCode. No matter if you are a beginner or a master, there are always new topics waiting for you to explore.
leetcode.com
Palindromic substring.. 구글 번역으로 회문 부분문자열.. 무슨 말인지 처음에 이해를 못했다. ( 영어실력의 부족.. )
그냥 '일요일', '토마토', '이효리' 마냥 앞으로 읽어도, 뒤로 읽어도 같은 문자열을 의미하는 것이다.
문제 예시 1-4 주어지는 문자열 s에 대해서 위에서 언급한 회문 부분문자열 중 가장 긴 값을 구하는 문제이다.
예시 1번처럼 'babad' 는 답이라고 할수있는 값이 'bab','aba' 두 개이다. 이 중 아무거나 반환해주면 된다.
문자열이 1개(예시 4)이거나 회문 부분문자열이 없는 경우(예시 5) 첫번째 문자를 반환해주면 된다.
주어진 예시에서 없는 내용의 예시로 하나를 들자면,
'abaaba' 가 주어진다면, 회문 부분문자열은 총 4개 'aa','aba','baab','abaaba'가 될 것이고,
답으로 가장 긴 값인 'abaaba'를 반환하면 된다.
위의 예제로 좀 더 코딩에 가깝게 고민해본다면, 회문 부분문자열은 앞뒤의 문자가 동일해야한다.
첫번째 값 'a'로 회문부분문자열이 만들어질려면, 우선 'a'가 또 있어야만 한다. 즉 'a' 와 'baaba'에서
'a' 가 존재하는 지를 판단해야한다. 만약 존재하지 않는다면 'a'로 만들수 있는 회문 부분문자열은 없다.
if 'a' in 'baaba': # 회문 부분문자열 검사 가능 else: # 할필요 없으니 pass
그리고 'a'가 여러 개가 존재할 수 있으므로, 모든 부분에 대해서 검사해야한다.
( 'aba' , 'abaa', 'abaaba' ) 해당 문자열이 회문 부분문자열이 될 수 있는지 검사해야하는 대상이다.
모든 부분에 대해서 검사해야하지만, 우리는 가장 큰 값을 원하기 때문에 맨 뒤에서 부터 검사하여,
값이 구해진다면 앞의 작은 문자열들은 검사할 필요가 없어진다. ( 코딩에서 종단조건으로 쓰여진다. )
res_list = [idx for idx, value in enumerate('baaba') if value == 'a'] # 'a'를 가지고 있는 index 값을 List로 만들어 주는 코드 res_list.reverse() # 만들어진 List를 역순으로 만들어야 맨 뒤에서 부터 검사할 수 있다.
이제 'abaaba' 를 먼저 회문 부분문자열 검사를 한다.
s='abaaba' first=0 last=5 while first < last : # 종단조건 if s[first] == s[last]: # 앞의 값과 뒤의 값이 같아야만 회문 부분문자열에 성립 first+=1 last-=1 # first,last 한 칸씩 앞으로,뒤로 옮긴다. else: # 같지 않으면 회문 부분문자열이 아니므로 더이상 검사하지 않는다. break if first>=last: # 회문부분문자열이 맞다면 break에 걸리지 않고 종단조건에 걸린다. ret = s[0:5] # 'abaaba'는 회문 부분문자열이 맞으므로 저장해준다.
해당 while문을 끝까지 돈다면, 회문 부분문자열이 되고 first>= last 조건이 성립하게된다. 이를 저장해준다.
그 후 두 번째로 큰 문자열을 검사해야하지만, 가장 큰 회문 부분문자열이 될 수 있는 문자열에서 값이 나왔으므로,
아래는 더 검사할 필요가 없겠다.
위의 코드들을 합쳐서 만든 코드는 아래와 같다.
문제풀이)
class Solution: def longestPalindrome(self, s: str) -> str: ret="" if len(s)==1: #주어진 string이 하나면 그대로 반환 return s elif len(s)==2: # string이 두개면 바로 비교 후 반환 if s[0]==s[1]: return s else: return s[0] else: for i in range(len(s)): if len(ret) >len(s[i:]): # 이미 저장한 회문부분문자열의 길이가 새로 비교할 전체 문자열보다 길다면 검사할 필요 없음 break if s[i] in s[i+1:]: res_list = [idx for idx, value in enumerate(s[i+1:]) if value == s[i]] res_list.reverse() for d in res_list: first=i last=d+i+1 if len(ret) > len(s[first:last+1]): # 구한 회문부분문자열 길이가 더 크면 검사할 필요 없음 break while first < last : # 회문 부분문자열 검사 코드 if s[first] == s[last]: first+=1 last-=1 else: break if first>=last: if len(s[i:d+i+1+1]) > len(ret): # 이번에 구한 회문 부분문자열 값이 기존 값보다 크면 변경 ret=s[i:d+i+1+1] else: continue if ret=="": # 회문 부분 문자열이 없을 경우 첫번째 값 반환 return s[0] return ret
해당 결과는 성공했지만, 성능이 좋진 않았다.
실행시간이 너무 긴 것을 보면, 좀 더 줄일 수 있는 방법을 고려해야 할 것 같다.
실행시간이 짧은 코드를 보니 for 한번으로 돌려버린 저런 멋진 코드.. 최고다..
string == string[::-1] # 회문 부분문자열을 검사하는 코드.. 나의 python 무지함이 드러나는 킬포.. class Solution: def longestPalindrome(self, string: str) -> str: if len(string) <= 1 or string == string[::-1]: return string start = 0 length = 1 for i in range(len(string)): odd = string[i - length - 1 : i + 1] even = string[i - length : i + 1] if 0 <= i - length - 1 and odd == odd[::-1]: start = i - length - 1 length += 2 elif 0 <= i - length and even == even[::-1]: start = i - length length += 1 return string[start : start + length]
반응형'IT > 자기계발 ( Leetcode )' 카테고리의 다른 글
2021-01-21] Find the Most Competitive Subsequence (0) 2021.01.22 2021-01-20] Valid Parentheses (0) 2021.01.20 2021-01-17] Count Sorted Vowel StringsSolution (0) 2021.01.18 2021-01-18] Max Number of K-Sum Pairs (0) 2021.01.18 2021-01-16] Kth Largest Element in an Array (0) 2021.01.16