코딩테스트/기타

[투포인터] 최대 길이 연속부분수열 .java

머밍 2024. 10. 27. 10:23

설명

0과 1로 구성된 길이가 N인 수열이 주어집니다. 여러분은 이 수열에서 최대 k번을 0을 1로 변경할 수 있습니다. 여러분이 최대 k번의 변경을 통해 이 수열에서 1로만 구성된 최대 길이의 연속부분수열을 찾는 프로그램을 작성하세요.

만약 길이가 길이가 14인 다음과 같은 수열이 주어지고 k=2라면

1 1 0 0 1 1 0 1 1 0 1 1 0 1

여러분이 만들 수 있는 1이 연속된 연속부분수열은

이며 그 길이는 8입니다.

입력

첫 번째 줄에 수열의 길이인 자연수 N(5<=N<100,000)이 주어집니다.

두 번째 줄에 N길이의 0과 1로 구성된 수열이 주어집니다.

출력

첫 줄에 최대 길이를 출력하세요.

예시 입력 1 

14 2
1 1 0 0 1 1 0 1 1 0 1 1 0 1

예시 출력 1

8

 

 

 내 풀이

 

1. rt가 가리키는 값이 0이면 0의 개수를 의미하는 zeroCount를 하나 증가

2. zeroCount가 k라면 현재의 길이(rt - lt + 1)을 최댓값으로 갱신

3. 만약 zeroCount가 k보다 크면 0의 개수를 줄이기 위해 lt의 값이 0이면 0의 개수를 줄임 => lt++

 

zeroCount가 k보다 커지는 그 직전 인덱스까지가 최댓값임을 이용하려고 했지만

더 복잡해지는 것 같아 zeroCount가 k일 때의 모든 길이를 현재의 최댓값과 비교하여 계속 갱신하도록 구현했다

 


import java.util.Scanner;

public class Main {

    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);

        int n = sc.nextInt();
        int k  = sc.nextInt();
        int[] arr = new int[n];
        for (int i = 0; i < n; i++) {
            arr[i] = sc.nextInt();
        }

        int answer = 0;
        int lt = 0;
        int zeroCount = 0;
        
        for(int rt = 0; rt < n; rt++) {

            if(arr[rt] == 0) {//값이 0이면 0개수 증가
                zeroCount++;
            }

            while(zeroCount > k) {
                if(arr[lt] ==0) zeroCount--;//lt가 0이면 0개수 하나 감소
                lt++;//0개수가 감소하든 아니든 lt는 증가

            }
            if(zeroCount == k ) {//최댓값으로 갱신
                answer = Math.max(answer, rt-lt+1);}

        }

        System.out.println(answer);
    }
}

 

 

 

다른 풀이

내가 k가 2일 때만 길이를 갱신한 반면, k와 관계없이 계속 갱신하는 점만 다른 코드이다

 


import java.util.Scanner;

public class Main {
    public int solution(int n, int k, int[] arr){
        int answer = 0;

        int cnt = 0;//현재 0의 개수
        int lt = 0;

        for(int rt = 0; rt < n; rt++) {
            if (arr[rt] == 0) cnt++;
            while (cnt > k) {
                if(arr[lt] == 0) cnt--;
                lt++;
            }
            answer = Math.max(answer, rt - lt + 1);//갱신
        }
        return answer;
    }
    public static void main(String[] args) {
        Main T = new Main();
        Scanner sc = new Scanner(System.in);

        int n = sc.nextInt();
        int k  = sc.nextInt();
        int[] arr = new int[n];
        for (int i = 0; i < n; i++) {
            arr[i] = sc.nextInt();
        }

        System.out.print(T.solution(n, k, arr));
    }
}

 

 

 

 

 

💡💡

answer값을 갱신하는 순서가 고민이라 여러 번 실행했다

어차피 0의 개수가 k보다 크면 결국 k가 될 때까지 while문을 실행하기 때문에 이 while문 뒤에 배치하면 되었다

순서대로 생각하자~!!!