백준 20922[자바] java 겹치는 건 싫어
문제 링크: https://www.acmicpc.net/problem/20922
20922번: 겹치는 건 싫어
홍대병에 걸린 도현이는 겹치는 것을 매우 싫어한다. 특히 수열에서 같은 원소가 여러 개 들어 있는 수열을 싫어한다. 도현이를 위해 같은 원소가 $K$개 이하로 들어 있는 최장 연속 부분 수열
www.acmicpc.net
▶문제
홍대 병에 걸린 도현이는 겹치는 것을 매우 싫어한다. 특히 수열에서 같은 원소가 여러 개 들어 있는 수열을 싫어한다. 도현이를 위해 같은 원소가 K개 이하로 들어 있는 최장 연속 부분 수열의 길이를 구하려고 한다.
100000 이하의 양의 정수로 이루어진 길이가 N인 수열이 주어진다. 이 수열에서 같은 정수를 K개 이하로 포함한 최장 연속 부분 수열의 길이를 구하는 프로그램을 작성해보자.
▶입력
첫째 줄에 정수 N (1≤N≤200000)과 K (1≤K≤100)가 주어진다.
둘째 줄에는 a1,a2,...an이 주어진다 (1≤ai≤100000)
▶출력
조건을 만족하는 최장 연속 부분 수열의 길이를 출력한다.
▶해설
투 포인터로 접근할 수 있는 문제입니다. 조건을 살펴보겠습니다.
1. 같은 정수가 k개 이하로 포함되어야 한다.
2. 가장 긴 수열을 찾아라.
간단하게 접근할 수 있습니다.
변수 left, right를 정의하고, right의 해당하는 숫자의 개수가 k보다 작다면 개수에 +1을 해주고, right++를 해줘 다음 숫자를 받을 준비를 합니다.
하지만 right에 해당하는 숫자의 개수가 k와 같다면, 다음 숫자를 더하면 k보다 커지게 되므로 left에 해당하는 숫자의 count를 줄이고 left++를 해줘 위치를 한 칸 앞으로 당겨옵니다.
ex) n = 7 k = 2일 때 수열: 1 2 2 2 3 4 5
left = 0, right = 0;
1의 개수는 현재 0입니다. 따라서 0<2이므로 1의 개수를 1 개 늘려주고, right++를 합니다.
left=0, right = 1;
위와 동일
left= 0, right =2;
위와 동일
left =0, right =3
이때 k와 2의 개수가 같습니다. 따라서 left의 해당하는 1의 카운트 개수를 줄이고, left++을 해줍니다.
하지만 2의 개수를 줄인 것이 아니라 1의 개수를 줄인 것이므로 2의 개수 < k를 만족할 때까지 left++은 계속됩니다.
따라서 아래와 같은 식이 만들어집니다. cnt는 숫자의 개수를 담고 있습니다.
private static void two() { int left = 0; int right = 0; while(left<=right){ if(right<=n-1 && cnt[arr[right]] < k){ cnt[arr[right]]++; right++; } else if(cnt[arr[right]]==k){ cnt[arr[left]]--; left++; } result = Math.max(right-left,result); if(right==n){ return; } } }
전체 코드
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.*; import java.util.stream.Collectors; public class Main { static int n, k; static Map<String, Integer> map = new HashMap<>(); static int[] arr; static int[] cnt; static int result; public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String[] s = br.readLine().split(" "); n = Integer.parseInt(s[0]); k = Integer.parseInt(s[1]); String[] s1 = br.readLine().split(" "); arr = new int[n]; cnt = new int[100001]; for(int i=0; i<s1.length; i++){ arr[i] = Integer.parseInt(s1[i]); } two(); System.out.println(result); } private static void two() { int left = 0; int right = 0; while(left<=right){ if(right<=n-1 && cnt[arr[right]] < k){ cnt[arr[right]]++; right++; } else if(cnt[arr[right]]==k){ cnt[arr[left]]--; left++; } result = Math.max(right-left,result); if(right==n){ return; } } } }
'Alogorithm > 투포인터' 카테고리의 다른 글
백준 7453[자바] java 합이 0인 네 정수 (0) | 2022.06.13 |
---|---|
백준 15961[자바] java 회전 초밥 (0) | 2022.05.27 |
백준 22945 [자바] java 팀 빌딩 (0) | 2022.02.26 |
백준 22862 [자바] java 가장 긴 짝수 연속한 부분 수열 (large) (0) | 2022.01.09 |
댓글
이 글 공유하기
다른 글
-
백준 7453[자바] java 합이 0인 네 정수
백준 7453[자바] java 합이 0인 네 정수
2022.06.13 -
백준 15961[자바] java 회전 초밥
백준 15961[자바] java 회전 초밥
2022.05.27 -
백준 22945 [자바] java 팀 빌딩
백준 22945 [자바] java 팀 빌딩
2022.02.26 -
백준 22862 [자바] java 가장 긴 짝수 연속한 부분 수열 (large)
백준 22862 [자바] java 가장 긴 짝수 연속한 부분 수열 (large)
2022.01.09
댓글을 사용할 수 없습니다.