파이썬 알고리즘 6장: 문자열 조작

파이썬 알고리즘 6장: 문자열 조작

팰린드롬

앞뒤가 똑같은 단어나 문장으로, 뒤집어도 같은 단어 또는 문장을 팰린드롬이라고 한다.

def isPalindrome(s:str) -> bool:
    chars =[]
    for char in s:
        if char.isalnum():
            chars.append(char.lower())
    return chars == chars[::-1] #slicing을 통해 문자열을 뒤집어서 비교할 수 있다
s = 'race a car'
isPalindrome(s)
False
추가문제: 가장 긴 팰린드롬

*링크 : https://programmers.co.kr/learn/courses/30/lessons/12904

저는 아직 푸는 방법을 몰라 다른분의 해답을 참고하여 코드를 뜯어 이해하는 방법을 선택했습니다.

def longest_palindrom(s:str)->int:
    length =len(s) # length라는 함수에 s의 길이를 값으로 할당한다
    
    subs = [s[i:j+1] for i in range(length) for j in range(i,length)] # 첫번째 글자부터 끝까지, 두번째 글자부터 끌까지 이런 형태의 리스트가 반환된다
    
    max = 0
    for sub in subs:
        if sub == sub[::-1] and max <= len(sub): # sub와 sub[::-1]이 같고 sub의 길이가 max 보다 크거나 같다면
            max = len(sub) #제일 긴 값을 찾는거기 때문에 max값에 제일긴 palindrom의 숫자가 반영된다
    return max
            
print(longest_palindrom("토마토맛토마토"))
7

문자열 뒤집기

def reverse(s):
    s[:] = s[::-1]
    return s
s = ['h','e','l','l','o']
reverse(s)
['o', 'l', 'l', 'e', 'h']
def reverse(s):
    s.reverse()
    return s
reverse(s)
['o', 'l', 'l', 'e', 'h']

로그파일 재정렬

*문제 : https://leetcode.com/problems/reorder-data-in-log-files/

Each word after the identifier will consist only of lowercase letters, or;
Each word after the identifier will consist only of digits.
The letter-logs are ordered lexicographically ignoring identifier, with the identifier used in case of ties.
The digit-logs should be put in their original order.

logs = ["dig1 8 1 5 1","let1 art can","dig2 3 6","let2 own kit dig","let3 art zero"]
#LeetCode 해설
class Solution(object):
    def reorderLogFiles(self, logs):
        def f(log):
            id_, rest = log.split(" ", 1) #logs의 각 원소들을 " "로 나누고 split은 한번만 하여 앞값은 id_에 뒷값은 rest에 할당한다
            return (0, rest, id_) if rest[0].isalpha() else (1,) #rest가 문자이면 앞에 배치하고 아니면 뒤에 배치한다

        return sorted(logs, key = f)
a = Solution()
a.reorderLogFiles(logs)
['let1 art can',
 'let3 art zero',
 'let2 own kit dig',
 'dig1 8 1 5 1',
 'dig2 3 6']
# 책 해설
def reorderLogFiles(logs):
    letters,digits = [],[]
    for log in logs:
        if log.split()[1].isdigit(): #공백으로 나눈것 중 두번째(파이썬은 0이 첫번째 인자이다) 인자가 숫자면
            digits.append(log) # digits에 log를 추가한다
        else:
            letters.append(log) #공백으로 나눈것 중 두번째 인자가 숫자가 아니면
            
    letters.sort(key= lambda x: (x.split()[1:],x.split()[0])) # letters를 식별자를 제외한 문자열[1:]을 키로 하여 정렬하며, 동일한 경우 식별자로 정리한다
    return letters + digits # 문자로 구성된 로그가 숫자 로그보다 앞에 나와야 하고 숫자 로그는 원래 배치되로 유지어야 한다
reorderLogFiles(logs)
['let1 art can',
 'let3 art zero',
 'let2 own kit dig',
 'dig1 8 1 5 1',
 'dig2 3 6']

가장 흔한 단어

*문제: https://leetcode.com/problems/most-common-word/

Words in the list of banned words are given in lowercase, and free of punctuation. Words in the paragraph are not case sensitive. The answer is in lowercase.

import re
from collections import Counter
import string
from typing import List
paragraph = "Bob hit a ball, the hit BALL flew far after it was hit"
banned = ["hit"]
def mostCommonWord(paragraph:str,banned: List[str])->str:
    #구두점 제거, 소문자화 및 banned에 있는 단어 제거
    normalized = ' '.join(word.strip(string.punctuation) for word in paragraph.lower().split() if word not in banned ).split() 
    counters = Counter(normalized) # Counter함수를 활용하여 각 인자가 몇번 있는지 확인할 수 있다
    return counters.most_common(1)[0][0] #첫번째 값이 제일 많이 등장하는 단어이기 때문에 (1)로 그 값을 선택하고 리스트 안에 있는 튜플에서 단어를 추출한다

그룹애너그램

*문제 : https://leetcode.com/problems/group-anagrams/

from collections import defaultdict
word_list = ['eat','tea','tan','ate','nate','bat']
# 책 풀이
def groupAnagrams(strs:List[str]) -> List[List[str]]:
    temp = defaultdict(list) # 딕셔너리를 생성한다
    
    for i in strs:
        temp[''.join(sorted(i))].append(i) # word_list의 각각의 원소들을 알파벳순으로 정렬하여 딕셔너리의 키값으로 하고 정렬하지 않은 값을 value로 넣는다
                                              # 이렇게 하면 애너그램끼리는 같은 키값을 갖게 된다
    
    return temp.values() #리스트를 반환한다
groupAnagrams(word_list)
dict_values([['eat', 'tea', 'ate'], ['tan'], ['nate'], ['bat']])