사용한 것
- 효율적으로 최대 카드 수를 구하기 위한 upper bound
- 효율적으로 원하는 카드팩 수를 만들 수 있는지 확인하기 위한 투포인터
풀이 방법
- 최대 카드 수를 효율적으로 구하기 위해서 upper bound를 사용한다.
- 선택한 카드 수로 원하는 카드팩 수를 만족할 수 있는지 확인하기 위해 투포인터를 사용한다.
- 선택하지 않은 카드면
ct
, r
증가, picked
에 카드 추가
- 선택한 카드면 이전에 선택한 카드 다음 인덱스로
l
, r
설정하고 ct
, picked
초기화
ct
가 선택한 카드 수(numOfCards
)가 되면 카드팩 수(numOfCardPacks
) 증가
numOfCardPacks
가 원하는 카드팩 수(m
)이 되면 return true
코드
public class Main {
private static int n;
private static int m;
private static int[] arr;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] line = br.readLine().split(" ");
n = Integer.parseInt(line[0]);
m = Integer.parseInt(line[1]);
arr = new int[n];
StringTokenizer st = new StringTokenizer(br.readLine());
for (int i = 0; i < n; i++) {
arr[i] = Integer.parseInt(st.nextToken());
}
System.out.println(findMaxNumOfCards());
}
private static int findMaxNumOfCards() {
int l = 1;
int r = n / m;
while (l <= r) {
int mid = (l + r) / 2;
if (isPossible(mid)) {
l = mid + 1;
} else {
r = mid - 1;
}
}
return r;
}
private static boolean isPossible(int numOfCards) {
int l = 0;
int r = 0;
int ct = 0;
Set<Integer> picked = new HashSet<>();
int numOfCardPacks = 0;
while (r < n) {
int card = arr[r];
if (!picked.contains(card)) {
ct++;
r++;
picked.add(card);
} else {
while (arr[l] != card) {
l++;
}
l++;
r = l;
ct = 0;
picked.clear();
}
if (ct == numOfCards) {
numOfCardPacks++;
l = r;
r = l;
ct = 0;
picked.clear();
}
if (numOfCardPacks == m) {
return true;
}
}
return false;
}
}