BOJ 30804. 과일 탕후루
🙇♀️[Silver II] 과일 탕후루 - 30804
성능 요약
메모리: 2804 KB, 시간: 12 ms
분류
브루트포스 알고리즘, 구현, 두 포인터
제출 일자
2024년 10월 2일 15:45:10
문제 설명
은하는 긴 막대에 $N$개의 과일이 꽂혀있는 과일 탕후루를 만들었습니다. 과일의 각 종류에는 $1$부터 $9$까지의 번호가 붙어있고, 앞쪽부터 차례로 $S_1, S_2, \cdots, S_N$번 과일이 꽂혀있습니다. 과일 탕후루를 다 만든 은하가 주문을 다시 확인해보니 과일을 두 종류 이하로 사용해달라는 요청이 있었습니다.
탕후루를 다시 만들 시간이 없었던 은하는, 막대의 앞쪽과 뒤쪽에서 몇 개의 과일을 빼서 두 종류 이하의 과일만 남기기로 했습니다. 앞에서 $a$개, 뒤에서 $b$개의 과일을 빼면 $S_{a+1}, S_{a+2}, \cdots, S_{N-b-1}, S_{N-b}$번 과일, 총 $N-(a+b)$개가 꽂혀있는 탕후루가 됩니다. $(0 \le a, b;$ $a+b < N)$
이렇게 만들 수 있는 과일을 두 종류 이하로 사용한 탕후루 중에서, 과일의 개수가 가장 많은 탕후루의 과일 개수를 구하세요.
입력
첫 줄에 과일의 개수 $N$이 주어집니다. $(1 \le N \le 200\,000)$
둘째 줄에 탕후루에 꽂힌 과일을 의미하는 $N$개의 정수 $S_1, \cdots, S_N$이 공백으로 구분되어 주어집니다. $(1 \le S_i \le 9)$
출력
문제의 방법대로 만들 수 있는 과일을 두 종류 이하로 사용한 탕후루 중에서, 과일의 개수가 가장 많은 탕후루의 과일 개수를 첫째 줄에 출력하세요.
🚀풀이
슬라이딩 윈도우(Sliding Window) 기법을 사용한다.
left, right은 포인터 역할을 한다.
과일종류가 2개 이하일 때는 right가 오른쪽으로 이동하고, 2개 초과 될 경우에는 left가 오른쪽으로 이동한다. 이때 right - left + 1의 값을 구하고 이것의 최대값이 원하는 결과값이다.
🚀코드
#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
// 입력 받기
int N;
cin >> N;
// 과일 배열 S
vector<int> S(N);
for (int& x : S) cin >> x;
// 과일 종류별 빈도수 저장 (과일 종류는 1~9)
int freq[10] = { 0 };
int unique_count = 0;
int left = 0;
int max_length = 0;
// 슬라이딩 윈도우 적용
for (int right = 0; right < N; right++) {
// 현재 과일의 빈도 증가
if (freq[S[right]] == 0) {
unique_count++;
}
freq[S[right]]++;
// 과일 종류가 2를 초과하면 왼쪽 포인터 이동
while (unique_count > 2) {
freq[S[left]]--;
if (freq[S[left]] == 0) {
unique_count--;
}
left++;
}
// 현재 윈도우의 크기 업데이트
max_length = max(max_length, right - left + 1);
}
// 결과 출력
cout << max_length;
return 0;
}