Python 문자열 조작
출처 : 점프투파이썬 위키독스 https://wikidocs.net/4308
* 모든 문제는 leetcode에서 참조함*
Problem 1. 유효한 팰린드롬
Solution 1. 브루트포스 방식
In [1]:
import re
import collections
class Solution_1():
def valid_palindrome_1(string: str) -> bool: # 가장 먼저 떠오른 풀이
string = string.lower()
string = re.sub(r'^\w','',string) # 아래 두 풀이의 isalnum()은 브루트포스방식이지만 정규식 처리가 더 빠름
return string == string[::-1] # 문자열의 [::-1]은 내부적으로 C로 구현되어 있어 속도 좋음
def valid_palindrome_2(string: str) -> bool:
# list 사용
strs = []
for char in string:
if char.isalnum():
strs.append(char.lower())
while len(strs) > 1:
if strs.pop(0) != strs.pop(): # list의 pop(0)은 O(n)
return False
# 인덴트 위치를 여기로 해서 return True를 하면
# 양쪽에서 한번만 일치해도 바로 else로 작동해서
# 다 확인하기 전에 True 반환하고 함수 종료됨
return True
def valid_palindrome_3(string: str) -> bool:
# deque 사용
strs: Deque = collections.deque()
for char in string:
if char.isalnum():
strs.append(char.lower())
while len(strs) > 1:
if strs.popleft() != strs.pop(): # deque의 popleft()는 O(1)
return False
return True
In [2]:
# valid_palindrome_1
print(Solution_1.valid_palindrome_1('Hackers makes the Better-code!'))
print(Solution_1.valid_palindrome_1('A man, a plan, a canal: Panama'))
Out [2]:
In [3]:
# valid_palindrome_2
print(Solution_1.valid_palindrome_2('Hackers makes the Better-code!'))
print(Solution_1.valid_palindrome_2('A man, a plan, a canal: Panama'))
Out [3]:
In [4]:
# valid_palindrome_3
print(Solution_1.valid_palindrome_3('Hackers makes the Better-code!'))
print(Solution_1.valid_palindrome_3('A man, a plan, a canal: Panama'))
Out [4]:
Solution 2. Two pointer solution
In [5]:
class Solution_2:
# 2 pointer 풀이
def valid_palindrome_4(s: str) -> bool:
l, r = 0, len(s)-1
while l < r:
while l < r and not s[l].isalnum():
l += 1
while l <r and not s[r].isalnum():
r -= 1
if s[l].lower() != s[r].lower():
return False
l +=1; r -= 1
return True
# 2 pointer 풀이 2
def valid_palindrome_5(s: str) -> bool:
beg, end = 0, len(s) - 1
while beg <= end:
while not s[beg].isalnum() and beg < end: beg += 1
while not s[end].isalnum() and beg < end: end -= 1
if s[beg] == s[end] or s[beg].upper() == s[end].upper():
beg, end = beg + 1, end - 1
else:
return False
return True
In [6]:
print(Solution_2.valid_palindrome_4('Hackers makes the Better-code!'))
print(Solution_2.valid_palindrome_4('A man, a plan, a canal: Panama'))
Out [6]:
In [7]:
print(Solution_2.valid_palindrome_5('Hackers makes the Better-code!'))
print(Solution_2.valid_palindrome_5('A man, a plan, a canal: Panama'))
Out [6]:
Problem 2. 문자열 뒤집기
Solution 1. Two pointer solution
In [8]:
def reverse_string_1(strs: list) -> None:
left, right = 0, len(strs) - 1
while left < right:
strs[left], strs[right] = strs[right], strs[left]
left += 1
right -= 1
In [9]:
reverse_string_1(['h','e','l','l','o'])
reverse_string_1(['H','a','n','n','a','h'])
Solution 2. Pythonic solution : reverse()
In [10]:
def reverse_string_2(strs: list) -> None:
strs.reverse()
In [11]:
reverse_string_2(['h','e','l','l','o'])
reverse_string_2(['H','a','n','n','a','h'])
Solution 1. lambda and list + operator
In [12]:
def reorder_log_files(logs: list) -> list:
letters, digits = [], []
for log in logs:
if log.split()[1].isdigit():
digits.append(log)
else:
letters.append(log)
# 2개의 키를 람다 표현식으로 정렬
letters.sort(key = lambda x: (x.split()[1:], x.split()[0]))
return letters + digits
In [13]:
logs = ['dig1 8 1 5 1', 'let1 art can', 'dig2 3 6', 'let2 own kit dig', 'let3 art zero']
reorder_log_files(logs)
Out[13]:
보충자료 1. lambda
lambda expression
- 식별자 없이 실행 가능한 함수 - 함수 선언 없이 하나의 식으로 함수를 단순하게 표현 가능 - 즉 간단하나 함수를 쉽게 선언하는 방법 - map, filter와 함께 쓰면 가독성이 떨어지니 주의 - 특별한 경우가 아니면 대부분 list comprehension을 활용
참고할 자료 : How to Use Python Lambda Functions – Real Python
보충자료 2. sort의 key options / sort와 sorted()의 차이
How to Use sorted() and sort() in Python – Real Python
Solution 1. 정규식 & Counter 객체
In [14]:
def most_common_word(paragraph: str, banned: list) -> str:
words = [word for word in re.sub(r'[^\w]', ' ', paragraph).lower().split() if word not in banned]
counts = collections.Counter(words)
return counts.most_common(1)[0][0]
In [15]:
most_common_word('Bob hit a ball, the hit BALL flew far after it was hit.', 'hit')
Out[15]:
Solution 1. defaultdict 객체 & 정렬
In [16]:
import collections
def group_anagrams(strs: list) -> list:
anagrams = collections.defaultdict(list)
for word in strs:
# 정렬 후 딕셔너리에 추가
anagrams[''.join(sorted(word))].append(word)
return list(anagrams.values())
In [17]:
group_anagrams(['eat','tea','tan','ate','nat','bat'])
Out[17]:
Solution 1. ✨✨중앙을 중심으로 확장하는 two poiter
In [18]:
def logest_palindrome(s: str) -> str:
def expand(left: int, right: int) -> str:
while left >= 0 and right <= len(s) and s[left] == s[right - 1]:
left -= 1
right += 1
return s[left+1 : right-1]
if len(s) < 2 or s == s[::-1]:
return s
result = ''
# 슬라이딩 윈도우 우측으로 이동
for i in range(len(s) - 1):
result = max(result,
expand(i, i + 1),
expand(i, i + 2),
key=len)
return result
In [19]:
logest_palindrome('babad')
Out[19]:
출처 : 파이썬 알고리즘 인터뷰
'Python > Algorithm' 카테고리의 다른 글
[Python] Linked List (2) (0) | 2021.09.02 |
---|---|
[Python] Linked List (1) (0) | 2021.09.01 |
[Python] Array (2) (0) | 2021.08.31 |
[Python] Array (1) (0) | 2021.08.30 |