白俊20922、重ねたくない-ダブルポインタ



https://www.acmicpc.net/problem/20922
1.アイデア

  • n最大値:2 x 10^5
    =>時間的複雑度はOより小さくなければならない(n^2)

  • 「連続」セクションの数
    =>連続したプロパティを使用して、二重ポインタを使用

  • 2つのポインタptr1,ptr2から

  • 次の手順を繰り返し、[0]が最後の要素を指すまで
  • 1)ptr2指す要素の出現回数<ptr2

  • 現在のkが示す要素出現回数+1
  • ptr2右に1マス移動(ptr2)
  • 2)ptr2++指す要素の出現回数>=ptr2
  • k<ptr2の要素の出現回数<kを指す.ptr1右に1マス移動(ptr1++)
  • 2.資料構造
  • int[] count:要素出現数
    ex)count[10] = 2の場合、要素10は2回現れる
    =>[1]~[100,000]使用
    =>メモリ:4 x 10^5 byte=0.4 MB
  • 3.時間複雑度
  • 約O(n)
    =>n導入最大値:2 x 10^5<<1億
  • コード#コード#
    import java.io.*;
    import java.util.StringTokenizer;
    
    public class Main {
    	static int n, k;			// 수열 길이 n, 최소 동일 원소 개수 k
    	static int[] numbers;
    	static int maxLen = Integer.MIN_VALUE;	// 동일 원소가 k개 이하인 최장 "연속 부분수열" 길이
    	static int[] count = new int[100001];	// 원소 등장 횟수
    
    	static void solution() {
    		int ptr1 = 0;
    		int ptr2 = 0;
    
    		// ptr2 가 마지막 원소를 가리킬 때까지 반복
    		while (ptr2 < n) {
    			int numPtr2 = numbers[ptr2];		// ptr2 가 가리키는 수열의 원소
    
    			if (count[numPtr2] < k) {
    				count[numPtr2]++;
    				ptr2++;
    			}
    			else {		// 동일 원소가 k번 초과하여 등장
    				count[ numbers[ptr1] ]--;
    				ptr1++;
    			}
    
    			maxLen = Math.max(maxLen, ptr2 - ptr1);
    		}
            
    //		int num;			// ptr2 가 가리키는 원소 값
    
    //		// ptr2 가 마지막 원소를 가리킬 때까지 반복
    //		while (ptr2 < n) {
    //			num = numbers[ptr2];
    //			count[num]++;
    //
    //			if (count[num] > k) {		// 동일 원소가 k번 초과 등장
    //				maxLen = Math.max(maxLen, ptr2 - ptr1);
    //
    //				// 동일 원소의 등장 횟수가 k번 이하가 될 때까지, ptr1++
    //				while (count[num] > k) {
    //					count[ numbers[ptr1] ]--;
    //					ptr1++;
    //				}
    //			}
    //
    //			ptr2++;
    //		}
    //
    //		// ptr2 가 마지막 원소를 가리킨 상태
    //		maxLen = Math.max(maxLen, ptr2 - ptr1);
    	}
    
    	public static void main(String[] args) throws IOException {
    		BufferedReader br = new BufferedReader(
    				new InputStreamReader(System.in)
    		);
    		StringTokenizer st = new StringTokenizer(br.readLine());
    
    		n = Integer.parseInt(st.nextToken());
    		k = Integer.parseInt(st.nextToken());
    
    		numbers = new int[n];
    		st = new StringTokenizer(br.readLine());
    		for (int i = 0; i < n; i++)
    			numbers[i] = Integer.parseInt(st.nextToken());
    
    		solution();
    		System.out.println(maxLen);
    	}
    }