[Programmers][Python][67258][카카오 인턴] 보석 쇼핑
문제 링크
첫 번째 풀이
투 포인터
기본적으로 투포인터는 부분합이 m이 되는 구간의 갯수를 찾는 문제입니다. left와 right는 0으로 시작합니다. s = [left,right]의 합입니다.
- s == m 일때는 ans += 1, right += 1
- s < m 일 때는 right += 1, s+= arr[right]
- s > m 일 때는 s -= arr[left], left += 1
left<=right 조건을 만족하면서 증가하기 때문에 $O(n)+O(n) = O(n)$의 시간복잡도를 가집니다.
항공대 알고리즘 소학회 천수환님의 투 포인터 강의는 여기에서 확인하실 수 있습니다 ^^7
정답 코드
위에서 구간합을 구하는 과정을 보석의 갯수를 구하는 과정으로 바꾸어서 진행합니다.
counter를 사용해서 list안에 unique한 값의 갯수를 num_of_type으로 가져옵니다. left와 right 범위에 있는 unique value의 갯수는 right가 증가할 때 없는 값이 추가되면 늘어나고, left에서 유일한 값이 사라지면 줄어듭니다. ans = {‘RUBY’:0} 일 때 ‘RUBY’ in ans가 True를 리턴한다는 점에 유의해서 del을 해주어야 합니다.
ans에 처음 값을 넣어두고 left, right = 0,1로 시작하는 부분에서 구현력이 필요하다고 생각합니다. 깔끔하게 짜는게 쉽지 않네요! 생각해보니 cnt_of_type를 안쓰고 len(ans)를 사용해도 되겠습니다.
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
31
32
33
34
35
36
from collections import Counter
def solution(gems):
n = len(gems)
num_of_type = len(Counter(gems).keys())
ans = {gems[0]: 1}
cnt_of_type = 1 # 찾은 unique value의 갯수 1로 시작
left, right = 0, 0
answer = [0, n - 1]
while left <= right:
# 정답 찾은 경우
if cnt_of_type == num_of_type:
# 더 짧은 답 갱신
if right - left < answer[1] - answer[0]:
answer = [left, right]
# left += 1
if ans[gems[left]] == 1:
del (ans[gems[left]])
cnt_of_type -= 1
else:
ans[gems[left]] -= 1
left += 1
# 부족한 경우
elif cnt_of_type < num_of_type:
# right += 1
right += 1
# 구간 확인
if right == n:
break
if gems[right] in ans:
ans[gems[right]] += 1
else:
ans[gems[right]] = 1
cnt_of_type += 1
return [answer[0]+1, answer[1]+1]
Success Notice: 수고하셨습니다.
Leave a comment