티스토리 뷰
책에 나온 문제에 추가적인 조건을 더해야 문제를 풀 수 있어요.
case-insensitive란 대소문자를 구별하지 않는다는 뜻이에요. 그리고 결과는 항상 소문자로 반환해요.
📝 풀이
책의 풀이와 달라요. 제가 생각하기에 더 빠른 속도의 알고리즘이에요(O(N^2) -> O(N)).
문제의 조건에 위배되는 입력을 할 경우 무한 루프에 빠질 수 있어요.
문제의 조건에 맞는 입력을 했다는 가정하에 풀이했어요.
def my_solution(paragraph: str, banned: [str]) -> str:
from collections import Counter
import re
banned_dict = dict(Counter(banned))
paragraph_dict = Counter([word for word in re.sub(r'[^\w]', ' ', paragraph).lower().split()])
while paragraph_dict:
if paragraph_dict.most_common(1)[0][0] in banned_dict:
del paragraph_dict[paragraph_dict.most_common(1)[0][0]]
continue
return paragraph_dict.most_common(1)[0][0]
🧐 고민
1. banned의 처리
banned에 포함되어있는지 여부를 확인하는 방법을 고민했어요. 책에서는 if word not in banned를 하는데, 이렇게 되면 검색마다 O(N)의 로직이 추가가 되는 문제가 생겨요. 그래서 저는 O(1)으로 확인을 하는 방법으로 딕셔너리를 생각했어요.
근거가 필요할 것 같아서 검색을 해봤어요.
파이썬에서 리스트와 딕셔너리 검색 속도 비교를 확인해보면 분명히 딕셔너리와 리스트에서 검색 속도가 차이 나는 것을 확인할 수 있어요. 물론, 이 문제에서는 속도 차이가 크지 않겠지만 알고리즘 풀이의 목적 자체가 조금 더 효율적인 방식을 찾는 것이라 이렇게 작성해봤어요.
또한, 딕셔너리를 직접 만들어주는 것이 아니라 내장 함수인 Counter를 통해서 쉽게 구현했어요.
2. 전처리 방식
re.sub(r'[^\w]', ' ', paragraph)
위의 코드를 이해하기 위해선 정규표현식에 대한 이해가 필요해요.
우선 sub 메서드를 살펴볼게요. python의 정규표현식 모듈 re의 메서드인 sub은 특정 문자열 타입(r'[^\w]')을 두 번째 문자열(' ')로 바꾸는 메서드예요. 물론 세 번째 인자는 검색할 대상 문자열이겠죠. 그래서 위의 식을 다시 해석해보면 아래와 같아요.
paragraph라는 문자열에서 r'[^\w]' 타입인 문자열을 찾아 ' '의 공백으로 변경해요.
그럼 이제 '^\w'를 볼게요. '^' 표시는 not을 의미하며 '^x'는 문자열 x가 아닌 것을 의미해요. 그럼 '\w'가 아닌 문자열을 의미할텐데, 여기서 w는 word를 의미해요. 즉, 단어가 아닌 문자열을 공백 문자열로 처리해주는 것이므로 쉼표(,), 마침표(.) 등을 공백으로 바꿔줄 거예요.
3. most_common
최댓값을 찾는 로직을 고민했어요. 만약에 most_common이 O(N)으로 값을 검색하는 것이면 사실 1번의 고민은 무의미해지거든요. 어차피 반복문 안에 O(N)이니까요. 하지만 Counter의 most_common 메서드는 내부적으로 heap으로 구현되어있어요. 그래서 가장 큰 값을 추출하는데 O(N)이 아니라 O(1)이 되겠죠. 그래서 most_common을 활용했어요.
def most_common(self, n=None):
'''List the n most common elements and their counts from the most
common to the least. If n is None, then list all element counts.
>>> Counter('abracadabra').most_common(3)
[('a', 5), ('r', 2), ('b', 2)]
'''
if n is None:
return sorted(self.iteritems(), key=_itemgetter(1), reverse=True)
return _heapq.nlargest(n, self.iteritems(), key=_itemgetter(1))
🐾 문제 링크 가기
https://leetcode.com/problems/most-common-word/
'알고리즘 학습 > 파이썬 알고리즘 인터뷰' 카테고리의 다른 글
[Leet Code] 937. Reorder Log Files(로그 파일 재정렬) (0) | 2021.12.08 |
---|---|
[Leet Code] 125. Valid Palindrome(유효한 팰린드롬) (0) | 2021.12.05 |
[LeetCode] 234.Palindrome Linked List(팰린드롬 연결 리스트) (0) | 2021.03.23 |
[파이썬 알고리즘 인터뷰] - 7장 p.193 (Leet Code 238번) (0) | 2021.01.05 |
[파이썬 알고리즘 인터뷰] - LeetCode 15. 3Sum (7장) (0) | 2020.11.23 |
- Total
- Today
- Yesterday
- API#lazy#
- 병든 나이트#BOJ#탐욕법#Python
- 섬의개수#백준알고리즘#Python
- django
- 나무자르기#BOJ#이분탐색#Python
- filter#isalnum#lower
- 쿼드트리#BOJ#분할정복#Python
- 반복수열#백준알고리즘#Python
- 미로 탐색#백준알고리즘#Python
- 날짜 계산#BOJ#완전탐색#Python
- 백준 알고리즘#BackTracking
- PassingCars#Codility#Python
- 토마토#백준알고리즘#Python
- Swift#Tuples#Range
- Distinct#Codility#Python
- NumberofDiscIntersections#Codility#Sort#Python
- 순열사이클#BOJ#Python
- 랜선자르기#이분탐색#BOJ#Python
- Triangle#Sorting#Codility#Python
- django#slicing
- 종이자르기#분할정복#BOJ#Python
- N으로 표현#DP#Programmers#Python
- Brackets#Stacks and Queues#Codility#Python
- 텀 프로젝트#백준알고리즘#Python
- 리모컨#완전탐색#BOJ#Python
- 배열합치기#분할정복#BOJ#Python
- 파이썬알고리즘인터뷰#4장
- 공유기 설치#BOJ#이분탐색#Python
- 터틀비치#리콘#xbox#controller
- 암호코드#dp#BOJ#Python
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |