[Java] 모든 종류를 포함하는 최단 구간 구하기
2021. 8. 11. 19:09
1. 문제
- 배열 gems는 진열되어 있는 모든 보석을 나열한 것
- 모든 보석을 하나 이상 포함하는 최단 구간을 찾아 { 시작 진열대 번호, 끝 진열대 번호 } 형식으로 반환
- 최단 구간이 여러개일 경우 시작 진열대 번호가 가장 작은 구간을 반환
2. 해결
- set 이용하여 종류 개수 구하기
- map 이용하여 종류 별로 둘 이상인지 확인
- queue 이용하여 최단 구간 구하기
- 투 포인터 알고리즘 이용 : 우선 구간의 시작점을 고정시킨 후 끝점을 한칸씩 증가시키며 최단 구간을 구한다. 그 다음 시작점을 한칸 증가시켜 앞과 같은 과정을 반복하여 최종적으로 가장 짧은 구간을 구한다.
import java.util.*;
class GetMinSection {
public int[] getMinSection(String[] gems) {
int[] section = new int[2]; // 최단 구간의 시작과 끝 번호 저장
HashSet<String> set = new HashSet<>(); // 보석 종류 저장
HashMap<String, Integer> map = new HashMap<>(); // 종류별로 보석이 몇 개 인지 저장
Queue<String> q = new LinkedList<>(); // 최단 구간에 포함되는 보석 순서대로 저장
// 보석의 종류 찾기
for(String s : gems) {
set.add(s);
}
int len = gems.length; // 최단 구간의 길이를 저장 - 초기값은 진열대의 길이(가장 큰 값)
int start = 0; // 큐에 들어간 첫번째 요소를 가리킴
int startPoint = 0; // 최단 구간의 시작점
// 진열대의 보석을 큐에 순서대로 삽입하면서 모든 종류를 포함하는 최단 구간인지 검사
for(int i = 0; i < gems.length; i++) {
q.offer(gems[i]);
map.put(gems[i], map.getOrDefault(gems[i], 0) + 1); // 종류별로 보석의 개수 저장
while(true) {
// 큐에 들어있는 첫번째 보석이 마지막 보석과 같은 경우
String temp = q.peek();
if(map.get(temp) > 1) {
// 첫번째 보석을 큐에서 삭제
q.poll();
map.put(temp, map.get(temp) - 1);
start++; // 최단 구간의 시작점을 한칸 증가
}
else {
break;
}
}
// 모든 종류의 보석을 포함하고 새로운 최단 구간을 찾은 경우
if(map.size() == set.size() && q.size() < len) {
len = q.size(); // 새로운 최단 구간의 길이 저장
startPoint = start; // 새로운 최단 구간의 시작점 저장
}
}
section[0] = startPoint + 1; // 최단 구간의 시작번호
section[1] = startPoint + len; // 최단 구간의 끝번호
return section;
}
}
'코딩테스트 (Java &)' 카테고리의 다른 글
[Java] 트럭 여러 대가 다리를 건너는데 걸리는 최소 시간 (0) | 2021.08.27 |
---|---|
[Java] 가능한 제재 아이디 목록의 경우의 수 찾기 (0) | 2021.08.17 |
[Java] 정수 삼각형에서 가능한 경로 중 최대값 구하기 (0) | 2021.08.02 |
[Java] 최단 평균 작업 시간 찾기 (0) | 2021.07.30 |
[Java] 모든 사람이 심사를 받는데 걸리는 최소 시간 (0) | 2021.07.03 |