https://school.programmers.co.kr/learn/courses/30/lessons/67258
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
문제 요약
보석이 진열된 배열이 주어졌을 때, 모든 종류의 보석을 적어도 1개 이상 포함하는 가장 짧은 구간을 찾아라.
풀이
문제의 제한사항에서 gems
의 길이가 최대 100,000이라고 하니, 완전탐색을 할 경우 시간초과가 발생할 위험이 있다. 따라서 다른 접근법을 생각해봐야 한다.
리스트 내의 부분리스트를 투포인터로 차례차례 탐색하면서, 만약 모든 보석을 포함하는 부분리스트를 발견할 경우 이를 answer
배열에 저장한다. 그러한 다음 answer
배열을 부분 리스트의 구간의 길이와, 시작 인덱스를 기준으로 오름차순으로 정렬한 뒤 가장 첫 번째 원소를 리턴한다.
from collections import defaultdict
def solution(gems):
# 보석 종류의 수
n = len(set(gems))
answer = []
# 부분 리스트의 시작 인덱스
left = 0
# 보석의 종류, 해당 보석이 나타난 횟수 저장
gem_dict = defaultdict(int)
# right을 0부터 gems의 길이까지 반복
for right in range(len(gems)):
# 현재 보석이 나타난 횟수 업데이트
gem_dict[gems[right]] += 1
# right을 증가시켜 다음 보석으로 이동
right += 1
# gem_dict의 길이가 n과 동일하다면,
# 모든 종류의 보석을 포함하는 부분 리스트를 찾은 것.
while len(gem_dict) == n:
# gem_dict[gems[left]]를 1 감소시킨다
# 즉, 현재 보석을 부분리스트에서 시킨다.
gem_dict[gems[left]] -= 1
# 만약 해당 보석의 나타난 횟수가 0이 된다면,
# 이 보석은 더이상 부분 리스트에 존재하지 않는다는 의미이므로,
# gem_dict에서 해당 보석을 제거함.
if gem_dict[gems[left]] == 0:
del gem_dict[gems[left]]
# 다음 부분 리스트의 시작 인덱스 이동
left += 1
answer.append([left, right])
# answer를 부분 리스트의 길이, 시작 인덱스를 기준으로 정렬하고,
# 첫 번째 원소를 반환함.
return sorted(answer, key=lambda x: (x[1]-x[0], x[0]))[0]
728x90
'알고리즘' 카테고리의 다른 글
[프로그래머스 두 원 사이의 정수 쌍] 파이썬 풀이 (0) | 2024.06.23 |
---|---|
[프로그래머스 요격 시스템] - 파이썬 풀이 (0) | 2024.06.23 |
[프로그래머스 불량 사용자] 파이썬 풀이 (0) | 2023.06.01 |
[백준 15686 치킨 배달] - 파이썬 풀이 (골드 5) (0) | 2023.05.22 |
[프로그래머스 프렌즈4블록] - 파이썬 풀이 (0) | 2023.05.17 |