@ 파이썬 알고리즘 인터뷰 책의 내용을 다시 복기하기 위해 쓰는 글
애너그램 그룹화
정렬해서 사용하는 방법이 제일 쉬움
sorted()와 sort()의 차이 알아두기
-문자열에서는 sorted()만 가능 .sort() 안 됨
sort()하면 값 자체가 바뀜
sorted()는 리스트로 저장해서 반환
# sort()의 경우
# sort()의 경우
sort_test = [ 'd', 'c', 'b','a',]
sort_test.sort()
print(sort_test)
# 주의 할 것
sort_test4 = sort_test.sort()
print(sort_test4)
>>
['a', 'b', 'c', 'd']
None
#sorted()의 경우
# sorted()의 경우
sort_test2 = [ 'd', 'c', 'b','a',]
print(sorted(sort_test2))
print(sort_test2)
sort_test_len = [ 'd', 'ccc', 'bb','aaaa',]
print(sorted(sort_test_len, key=len)) #길이 순서로 sorted
sort_test_fn = [ 'adc', 'abc', 'azzzzzbb', 'bbb']
def fn(s):
return s[0], s[-1] # 처음 글자 순서로 먼저 정렬, 그 다음 마지막 글자 순서로 정렬
print(sorted(sort_test_fn, key=fn))
print(sorted(sort_test_fn, key=lambda x: (x[0], x[-1])))
>>
['a', 'b', 'c', 'd']
['d', 'c', 'b', 'a']
['d', 'bb', 'ccc', 'aaaa']
['azzzzzbb', 'adc', 'abc', 'bbb']
['azzzzzbb', 'adc', 'abc', 'bbb']
sorted()의 경우 하이퍼파라미터로 key=함수 를 사용이 가능하다
함수의 정의 된 순서로 정렬 된다.
# 문자열의 경우
# 문자열의 경우도 list로 반환됨
# 이를 다시 문자열로 바꿔주려면 join 이용하기
sort_test3 = 'dcba'
print(sorted(sort_test3))
print(''.join(sorted(sort_test3)))
>>
['a', 'b', 'c', 'd']
abcd
join() 매소드 정리
- 리스트를 문자열로 만들어서 join 해줌
-기본 형태 ''.join()
collections에서 defaultdict 가져오면 어떻게 찍히나 체크해보기
from collections import defaultdict
defaultdict(list)
>>
defaultdict(list, {})
+ 추가로 정렬에서 사용되는 알고리즘들..
- 퀵정렬
- 삽입정렬
- 힙정렬
- 버블정렬
- 병합정렬
- 팀정렬 (팀소트) : 삽입정렬을 쪼개서 사용하는 정렬 _ 현재 파이썬 기반이 되는 정렬
코딩 풀이
input)
words = ['eat', 'tea', 'tan', 'ate', 'nat', 'bat']
sol)
from collections import defaultdict
def groupAnagrams(words):
# defaultdict(list, {}) type으로 초기화
anagrams = defaultdict(list)
for word in words:
# 정렬해서 딕셔너리에 추가
# step 1. sorted(word)로 words[i]를 정렬
# step 2. anagrams의 key로 step 1을 사용
# step 3. anagrams의 key에 word를 append 해줌
anagrams[''.join(sorted(word))].append(word)
print(anagrams) # 어떻게 작동되는지 이해해보기
# anagrams의 value 값만 return
return list(anagrams.values())
groupAnagrams(words)
>>
아래는 내가 작동원리를 이해하기 위해서 찍어본 것
defaultdict(<class 'list'>, {'aet': ['ate']})
defaultdict(<class 'list'>, {'aet': ['ate'], 'abt': ['bat']})
defaultdict(<class 'list'>, {'aet': ['ate', 'eat'], 'abt': ['bat']})
defaultdict(<class 'list'>, {'aet': ['ate', 'eat'], 'abt': ['bat'], 'ant': ['nat']})
defaultdict(<class 'list'>, {'aet': ['ate', 'eat'], 'abt': ['bat'], 'ant': ['nat', 'tan']})
defaultdict(<class 'list'>, {'aet': ['ate', 'eat', 'tea'], 'abt': ['bat'], 'ant': ['nat', 'tan']})
>>
결과
[['ate', 'eat', 'tea'], ['bat'], ['nat', 'tan']]
가장 긴 팰런드롬 부분 문자열 출력
- 서로 공통된 가장 긴 부분 문자열 찾기
(ex, cp949 -> utf-8 변환)
※ 팬런드롬은 문자열 슬라이싱 이용하면 가장 빠르게 처리됨 (자기 자신을 예외처리 할 때 사용하기)
input)
pal_str = 'babttonottad'
pal_str2 = 'cbbd'
sol)
def longestPalindrome(pal):
# 팰런드롬 판별 및 투 포인터 확장
# left, right를 홀수, 짝수일 때 각각 하나 씩 키워, 탐색 구간을 늘리기
def expand(left, right):
# if1 탐색 구간의 left가 0보다 작아지면 글자X 탈출
# if2 탐색 구간의 right가 len(pal)과 같아지면 글자X 탈출
# if3 pal[left]와 pal[right]가 같지 않으면 더 이상 팰런드롬이 아니므로 탈출
while left >=0 and right < len(pal) and pal[left] == pal[right]:
# left, right 하나씩 키우기
left -= 1
right += 1
# 탈출을 한 순간 - 1 번째까지 팰런드롬이므로 그 string을 slicing해 return
return pal[(left + 1):right]
# 해당 사항이 없을 때 빠르게 리턴
# check 1 pal의 길이가 1개 또는 0개이면 그 자체가 팰런드롬
# check 2 pal 자체가 팰런드롬이면 빠르게 return 해서 시간복잡도 최악의 경우 제거
if len(pal) < 2 or pal == pal[::-1]:
return pal
result = ''
# 슬라이딩 윈도우 우측으로 이동
# step 1 길이만큼 i에 1씩 더해서 탐색
for i in range(len(pal) - 1):
# step 2 expand 함수 불러오기, left <- i, right <-i+1 or i+2 //2칸(짝수), 3칸(홀수) 넣음
# step 3 기존에 가장 큰 result 와 함수 expand를 통과한 두 결과값을 key=len(길이)로 비교
# step 4 그 중 가장 큰 값을 result에 저장
result = max(result, expand(i, i+1), expand(i, i+2), key=len)
return result
print(longestPalindrome(pal_str))
print(longestPalindrome(pal_str2))
ttonott
bb
'코딩테스트 연습 복기용' 카테고리의 다른 글
팰린드롬 문제 (0) | 2023.03.09 |
---|---|
하노이 탑 문제 (0) | 2023.02.23 |
230222 코딩 연습 (0) | 2023.02.22 |
230221 코딩 연습 (0) | 2023.02.21 |