다양한 종류의 문제가 존재하는 유형이다.
유형 1. 구간 내 최소 개수 사용하기
특정 구간 내에서 몇 개를 설치해야 전체를 커버할 수 있느냐 ~ 이런 유형의 문제이다.
풀이 방법만 알면 되게 쉽게 풀 수 있다.
- 진출 시점 (끝점) 기준으로 오름차순 정렬
- 반복문 순회하며 현재 진입시점이 이전 진출 시점보다 작으면 넘어가고, 현재 진입시점이 이전 진출 시점보다 크면 갱신하는 방식
아래 두 문제가 굉장히 유사한 문제다.
- 단속 카메라
https://school.programmers.co.kr/learn/courses/30/lessons/42884
def solution(routes):
answer = 1 # 시작지점에 1개
routes = sorted(routes, key=lambda x: (x[1], x[0]))
# 초기 진출 시점
prev_max_point = routes[0][1]
# 순회하면서
for idx in range(1, len(routes)):
# 현재 진입 시점이 이전 진출 시점보다 클 경우 - 커버가 안됨
if routes[idx][0] > prev_max_point:
answer += 1
prev_max_point = routes[idx][1]
return answer
- 요격 시스템
https://school.programmers.co.kr/learn/courses/30/lessons/181188
프로그래머스
SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
def solution(targets):
answer = 1
targets = sorted(targets, key=lambda x: (x[1], x[0]))
# print(targets)
prev_end_point = targets[0][1]
for i in range(1, len(targets)):
# print("## 현재 시작 구간", targets[i][0], "## 이전 최대 끝 구간", prev_end_point)
if targets[i][0] >= prev_end_point:
answer += 1
prev_end_point = targets[i][1]
return answer
유형 2. 최대값 만들기
미래를 알고 있기 때문에, 거꾸로 순회하면서 최대로 만드는 전략을 사용하면 된다.
- 주식
https://www.acmicpc.net/problem/11501
- 가장 마지막 날부터 거꾸로 탐색하면서,
- 현재까지의 최대 주가(max_price) 를 기억합니다.
- 매 날의 주가가 max_price보다 작다면, 그 날 사서 max_price에 판다고 가정하고 이익을 계산합니다.
- 총 이익을 누적하여 출력합니다.
import sys
def solve():
T = int(sys.stdin.readline()) # 테스트 케이스 수 입력
for _ in range(T):
N = int(sys.stdin.readline()) # 각 테스트 케이스의 날 수
prices = list(map(int, sys.stdin.readline().split())) # 날 별 주가 리스트
max_price = 0 # 현재까지의 최대 주가 (미래 기준)
profit = 0 # 누적 이익
# 주가 리스트를 뒤에서부터 탐색 (미래부터 현재로)
for price in reversed(prices):
if price > max_price:
# 더 비싼 날이 있으면, 그날을 기준으로 팔기 위해 max_price 갱신
max_price = price
else:
# 현재 주가가 max_price보다 낮으면, 지금 사서 max_price에 판다고 가정
profit += max_price - price
print(profit) # 해당 테스트케이스의 최대 이익 출력
# 함수 실행
solve()
유형 3. 문자열 탐색
문자열을 바꾸기 위해서 드는 비용 (e.g. 커서의 이동 위치 등) 을 그리디하게 탐색하는 문제.
https://school.programmers.co.kr/learn/courses/30/lessons/42860
프로그래머스
SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
def up_down(target):
return min(abs(ord(target) - ord('A')), abs(ord('Z') - ord(target) + 1))
def solution(name):
# 알파벳 변경 횟수, 커서 변경 횟수
spell_move = 0; cursor_move = len(name) - 1 # 최대 이동 거리
for idx, ch in enumerate(name):
# 상하이동부터
spell_move += up_down(ch)
# 해당 인덱스 다음부터 연속된 A 문자열 찾기
next_idx = idx + 1
while next_idx < len(name) and name[next_idx] == 'A':
next_idx += 1
# next_idx : 연속된 A 문자열의 오른쪽 끝 인덱스
# 정방향, 역방향 순회 거리 중 최소값 비교
distance = min(idx, len(name) - next_idx)
# 실제 이동 거리 계산 (순방향 VS 역방향 거리 계산)
print(name, ch)
print((cursor_move, idx + len(name) - next_idx + distance))
cursor_move = min(cursor_move, idx + len(name) - next_idx + distance)
answer = spell_move + cursor_move
return answer
유형 4. 우선순위 큐 활용 문제
- 무지의 먹방 라이브
https://school.programmers.co.kr/learn/courses/30/lessons/42891
프로그래머스
SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
그림처럼 정렬이 보장되어야 효율성 테스트를 통과할 수 있는 문제다.
따라서 항상 최소값을 뽑을 수 있도록, heapq를 결합하여 그리디를 사용한다.
import heapq
def solution(food_times, k):
# 애초에 먹을 음식 안남으면 -1 반환
if k >= sum(food_times):
return -1
food_list = []
length = len(food_times) # 남은 음식 개수
for i in range(length):
# (남은 시간, 음식 번호)
# 최소 힙을 통한 음식 시간 정렬
heapq.heappush(food_list, [food_times[i], i+1])
time = 0
# 블럭 단위로 뺄만큼 K가 남았다면 -> 묶음 단위로 빼주기
while (food_list[0][0] - time) * length < k:
k -= (food_list[0][0] - time) * length
time += food_list[0][0] - time
length -= 1
heapq.heappop(food_list)
# 최종적으로 K초에 몇 번째 음식이 오는지 구하기
result = sorted(food_list, key = lambda x: x[1])
answer = result[k % length][1]
return answer
'알고리즘 > 자료구조_알고리즘' 카테고리의 다른 글
[코테 직전 유형별 정리] - 이분탐색 (0) | 2025.03.21 |
---|---|
[코테 직전 유형별 정리] - DP (0) | 2025.03.21 |
[코테 직전 유형별 정리] - DFS / BFS (0) | 2025.03.21 |
[알고리즘] 01. DFS & BFS (0) | 2023.09.11 |
[알고리즘] 00. 자료구조 리마인드 (0) | 2023.09.11 |