해시(해시 테이블)이란 Key-Value를 맵핑하여 데이터를 저장하는 자료구조. 파이썬에서는 기본 제공되는 dict
딕셔너리 자료형을 사용하면 된다.
원소의 개수를 셀 때 해시와 collections 모듈의 Counter 클래스를 사용하면 좋다.
Operation | Dictionary | List |
---|---|---|
Get | O(1) | O(1) |
Insert | O(1) | O(1) ~ O(N) |
Update | O(1) | O(1) |
Delete | O(1) | O(1) ~ O(N) |
Search | O(1) | O(N) |
원소를 넣거나 삭제, 찾는 일이 많을 때에는 딕셔너리를 사용하는 것이 좋다
dict1 = {} # {}
dict2 = dict() # {}
del dict_obj[key]
만약 딕셔너리에 key가 없다면 keyError가 발생
pop(key[,default])
key 값에 해당하는 value를 리턴. key가 없다면 두번째 파라미터인 default를 리턴.
(만약 default 설정하지 않았을 시엔 keyError가 발생)
for key in dictionary:
for key, value in dictionary.items():
in
keys()
values()
sorted(dictionary.items())
: 오름차순 정렬, 정렬된 딕셔너리를 리스트 형으로 반환dictionary.keys()
로 정렬 : 정렬된 Key 값만 리스트로 반환dictionary.items()
로 정렬 : 튜플(Tuple) 형태로 Key값 기준으로 정렬된 리스트가 반환sorted(dictionary.items(), key=lambda item : item[1])
딕셔너리에 폰켓몬 이름을 기준으로 값을 넣어준다. 딕셔너리의 key값의 개수가 폰켓몬의 총 종류 수이므로 n/2
와 key값 길이를 비교하여 더 작은 값을 리턴하면 된다.
def solution(nums):
answer = 0
d = {}
for item in nums:
if item in d:
d[item] += 1
else:
d[item] = 1
if len(d.keys()) > (len(nums) / 2):
answer = len(nums) / 2
else:
answer = len(d.keys())
return answer
dict.fromkeys(key값, value)
메서드 : key값으로 지정할 리스트를 넘겨준 뒤 value로 지정할 값을 넘겨주면 딕셔너리를 생성하여 반환
참가자 이름을 기준으로 딕셔너리에 값을 넣어준다. 완주자 배열을 돌면서 딕셔너리에서 값을 빼주는데 (시간복잡도 O(1)
) 만약 값이 0이면 해당 키 값을 없애준다.
완주자와 참가자는 1명 차이가 나므로 최종적으로 딕셔너리에 남아있는 키 값이 완주하지 못한 선수의 이름이다.
def solution(participant, completion):
answer = ''
d = dict.fromkeys(participant, 0)
for p in participant:
d[p] += 1
for c in completion:
d[c] -= 1
if d[c] == 0:
del d[c]
for i in d.keys():
answer = i
return answer
엄청나게 삽질했던 문제. 이틀을 붙잡았다... 그리고 전화번호가 0~9 사이의 숫자로 시작할 수 있음을 잊고 풀어서 테케에서도 우수수 틀렸다.
sort()
추가 : 시간 초과 (효율성 3,4번)# 3. 효율성 3,4번 테케에서 시간초과 난 코드 (이렇게 풀면 안된다...)
def solution(phone_book):
answer = True
d = { str(i):[] for i in range(10) }
phone_book.sort()
for phone in phone_book:
if len(d[phone[0]]) == 0:
d[phone[0]].append(phone)
else:
for item in d[phone[0]]:
for i in range(min(len(item), len(phone))):
if item[i] != phone[i]:
break
if i == (min(len(item), len(phone)) - 1):
return False
d[phone[0]].append(phone)
return answer
(정답) sort()
를 해주고 나면 굳이 다 살펴볼 필요가 없음을 캐치해야 한다!!!!
['1', '11', '112', '345']
데이터를 정렬한 뒤에는 이렇게 생겼을 것이다. 그러면 접두사가 될 수 있는 요소는 바로 이전에 등장한 데이터이다. 굳이 다 살펴볼 필요가 없는 것!!
# 정답 코드
def solution(phone_book):
answer = True
phone_book.sort()
for i in range(len(phone_book)-1):
if phone_book[i] == phone_book[i+1][:len(phone_book[i])]:
return False
return answer
# 시간초과난 코드
import math
from itertools import combinations
def solution(clothes):
answer = 0
# 조합으로 뽑아내면 될 듯
data = {}
for item in clothes:
name, kind = item
if kind in data:
data[kind] += 1
else:
data[kind] = 1
case = []
for i in range(1, len(data.keys())+1):
case += list(combinations(list(data.keys()), i))
for item in case:
result = 1
for i in range(len(item)):
result *= (math.comb(data[item[i]], 1))
answer += result
return answer
# 나름 괜찮다 생각했건만 시간초과... ㅠㅠ
def solution(clothes):
answer = 0
data = {}
for item in clothes:
name, kind = item
if kind in data:
data[kind] += 1
else:
data[kind] = 1
case = []
for key in data:
if len(case) == 0:
case.append(data[key])
else:
origin_length = len(case)
for i in range(origin_length):
case.append(case[i] * data[key])
case.append(data[key])
answer = sum(case)
return answer
def solution(clothes):
answer = 1
data = {}
for item in clothes:
name, kind = item
if kind in data:
data[kind] += 1
else:
data[kind] = 1
for key,value in data.items():
answer *= (value + 1)
answer -= 1
return answer
딕셔너리 d
에 key로는 장르명, value로는 (재생횟수, 고유인덱스) 값을 부여했다.
딕셔너리 count
에 key로는 장르명, value로는 총 재생횟수의 총합을 구했다. 처음 reduce
함수를 사용해봤다!
reduce 함수는 파이썬3부터는 내장함수가 아니어 import를 해줘야 한다.
from functools import reduce
reduce 함수는 (집계함수, 순회가능한 데이터[, 초기값])
을 갖는다. 따라서 집계함수를 위해 lambda
를 사용했다.
조건에 맞춰서 데이터를 뽑으면 끝~!
# 한방에 통과해서 조금 눈물이 났다 기쁨의 눈물이...
from functools import reduce
def solution(genres, plays):
answer = []
d = {}
for i in range(len(genres)):
if genres[i] in d:
d[genres[i]].append((plays[i], i))
else:
d[genres[i]] = [(plays[i], i)]
count = {}
for key in d.keys():
d[key].sort(reverse=True, key=lambda x: (x[0], -x[1]))
# 재생횟수만 누적합
count[key] = reduce(lambda acc, cur: acc + cur[0], d[key], 0)
# [('장르명', 재생횟수 총합)]
sort_count = sorted(count.items(), key=lambda item: -item[1] )
for item in sort_count:
key = item[0]
if len(d[key]) == 1:
answer.append(d[key][0][1])
else:
answer.append(d[key][0][1])
answer.append(d[key][1][1])
return answer