LeetCode #49(Group Anagrams)

류성현·2022년 2월 19일

알고리즘(Python)

목록 보기
7/7

• 문제 분석

문자열 배열을 받아 애너그램 단위로 그룹핑하라

Example:
• Input: strs = ["eat","tea","tan","ate","nat","bat"]
• Output: [["bat"],["nat","tan"],["ate","eat","tea"]]

문제 분석이라 할 것이 딱히 없다. 말 그대로 문자열들이 요소인 배열을 입력 받아 애너그램, 즉 문자를 재배열 했을 때 다른 의미가 되는 단어들의 집합으로 만들라는 것이다. 위의 예시에서 보면 eat, ate, tea는 한 단어가 다른 문자 배열을 이루었을 때 같아지기 때문에 그룹핑한다.

• 문제 풀이

이러한 애너그램, 문자 배열을 다르게 했을 때 같아짐의 가능성을 따질 때는 정렬하여 비교하는 것이 가장 간단하다. 문자열을 정렬하여 비교했을 때 같다면, 그 둘은 애너그램인 것이다. 따라서 sorted() 함수(sort()라는 다른 정렬 함수도 있지만 이 둘의 본질적인 차이점은 정렬할 배열이 실제로 정렬이 되느냐 아니면 해당 배열은 유지하면서 정렬된 배열을 새롭게 리스트의 형태로 리턴하느냐의 차이이다. sort()는 전자, sorted()는 후자에 해당한다.)와 join() 함수(sorted() 함수를 사용하면 문자열이 정렬되지만 문자들의 리스트로 리턴되기 때문에 이를 다시 합쳐야한다)을 이용하여 정렬된 값이 같은 지를 비교한다. 이후 문자열이 정렬된 값을 키, 문자열 자체를 값으로 하는 딕셔너리를 생성하여 같은 애너그램끼리 그룹핑한다. 이때는 새로운 키 값에 대한 요소를 쉽게 다루기 위하여 collections.defaultdict()를 이용한다. 이를 정리하여 풀이한 코드는 다음과 같다.

import collections, typing

def groupAnagrams(strs: List[str]) -> List[List[str]]:
    anagrams = collections.defaultdict(list)
    
    for word in anagrams:
        anagrams[''.join(sorted(word))].append(word)
    
    return list(anagrams.values())

• 관련 문법 및 기능

-sorted()

위에 풀이에서 말했 듯, sorted()sort()와 달리 해당 배열을 실제로 정렬하여 변경하느냐 아니면 그 배열은 유지하되 정렬된 배열을 리스트의 형태로 리턴하느냐의 차이다. 참고롤 sort()None을 리턴한다. 디테일한 사용법도 조금씩 다른데 다음을 보자.

>>> l = [3, 2, 5, 7, 1, 9]
>>> sorted(l)
[1, 2, 3, 5, 7, 9]
>>> l
[3, 2, 5, 7, 1, 9]
>>> l.sort()
>>> l
[1, 2, 3, 5, 7, 9]

위와 같이 sorted()는 정렬할 리스트를 파라미터로 가져와 정렬할 수 있다. sort() 같은 경우에는 리스트 자료형이 제공하는 메소드로 [리스트].sort()의 형식으로 사용 가능하다. 또 sorted()는 문자열도 파라미터로 가져와 정렬할 수 있다. 다만 그 리턴값이 리스트의 형태이다. 따라서 이를 정렬된 하나의 문자열로 만들기 위해서는 앞에서 나올 join() 함수를 사용한다. 마찬가지로 정렬할 배열 그 자체의 값은 변하지 않는다.

>>> s = 'vazdfk'
>>> sorted(s)
['a', 'd', 'f', 'k', 'v', 'z']
>>> s
'vazdfk'
>>> ''.join(sorted(s))
'adfkvz'
>>> 

추가적으로 sorted()도 옵션으로 파라미터 key를 가진다. 이는 sort()에서의 사용법과 같으며 다음과 같이 적용할 수 있다.

>>> l = ['abc', 'cde', 'cbla', 'bb', 'efg']
>>> sorted(l, key=len)
['bb', 'abc', 'cde', 'efg', 'cbla']
>>> sorted(l, key=lambda x: x[1])
['abc', 'cbla', 'bb', 'cde', 'efg']
>>> sorted(l, key=lambda x: (x[0], x[-1]))
['abc', 'bb', 'cbla', 'cde', 'efg']

-join()

join()은 간단하다. 기본적인 형태는 '구분자'.join([리스트])이다. 다음 아주 간단한 사용법에 대한 예시 코드 보자.

>>> l = ['a', 'b', 'c', 'd']
>>> ''.join(l)
abcd
>>> ', '.join(l)
a, b, c, d
>>> ' / '.join(l)
a / b / c / d
>>> '\n'.join(l)
a
b
c
d

위와 같이 다양한 구분자를 이용하여 문자로 이루어진 배열을 하나의 문자열로 합칠 수 있다. 기본적으로는 구분자를 사용하지 않고 순수한 문자열로 만드는 상황이 많이 나오니 기억하면 좋다.

-dict_keys, dict_values, dict_items

딕셔너리가 제공하는 함수인 keys(), values(), items()는 파이썬 3.0 이전까지는 리턴값을 list의 형태로 반환하였다. 하지만 리스트로 반환했을 시 딕셔너리의 동적 변경을 반영하지 못한다는 이유와 메모리 효율성과 같은 이유로 파이썬 3.0 부터는 dict_keys, dict_values, dict_items라는 객체의 형태로 반환한다. 따라서 이를 리스트의 형태로 반환하기 위해서는 다음과 같이 강제로 캐스팅 해줘야한다.

>>> dict = {'key1': 'a', 'key2': 'b', 'key3': 'c'}
>>> dict.keys()
dict_keys(['key1', 'key2', 'key3'])
>>> dict.values()
dict_values(['a', 'b', 'c'])
>>> dict.items()
dict_items([('key1', 'a'), ('key2', 'b'), ('key3', 'c')])
>>> list(dict.keys())
['key1', 'key2', 'key3']
>>> list(dict.values())
['a', 'b', 'c']
>>> list(dict.items())
[('key1', 'a'), ('key2', 'b'), ('key3', 'c')]
profile
진짜 개발자가 되어보고 싶어 공부하는 신생아

0개의 댓글