본문 바로가기

Java/Java 알고리즘 인프런

[Ch.03 - 투 포인터] 6. 최대 길이 연속부분수열 ###

728x90
반응형

6. 최대 길이 연속 부분수열
0과 1로 구성된 길이가 N인 수열에서, 최대 k번 변경가능한데, 0을 1로 변경가능
최대 k번의 변경을 통해 1로만 구성된 최대 길이의 연속부분수열 출력

 

입력값

14, 2

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

출력값

8


1. answer와 sum -> 구간별 연속부분수열 개수를 sum에 저장해 answer와 비교

2. 포인터 1 p1, 포인터2 p2, p2의 개수 p2_n

3. 1로 바꾼 마지막 위치 zero, 현재 세고 있는 위치 count

4. arr2는 arr배열을 복사한 배열로, 매번 리셋

5.  while (p2 < n && p2_n < k)

if (arr[p2] == 0)

0인 값 1로 바꾸고

if(p2_n==1)

처음 1로 바꾼 위치 기억

else 

0이 아니므로 p2 증가

6. for (int i = count; i < n; i++)

if (arr[i] == 1)

1인 값이 존재하면 sum +1하고,

if (answer < sum)

결과값보다 sum이 크면 sum을 결과값에 대입

else

배열값이 1아니면 아니면 멈춤

6.  현재 세고 있는 위치와 1로 바꾼 마지막 위치 설정후 다시 반복

package twopointer.ch03;

//최대 길이 연속부분수열
//0과 1로 구성된 길이가 n인 수열
//최대 k번 0을 1로 변경해 최대 길이의 연속부분수열을 찾아라
//1 1 0 0 1 1 0 1 1 0 1 1 0 1

import java.util.Scanner;

class Twopointer06_1 {
	static int[] arr;

	public int solution(int n, int k) {
		int answer = 0;
		int sum = 0;
		int p1 = 0;
		int p2 = 0;
		int p2_n = 0;
		int zero=0;
		int count=0;
		// p2의 개수 세기
		int [] arr2= arr.clone();
		while (p1 < n-1) {
			arr=arr2.clone();
			while (p2 < n && p2_n < k) {
				
				if (arr[p2] == 0) {
					arr[p2] = 1;
					p2++;
					p2_n++;
					if(p2_n==1) {
						zero=p2;
					}
				}
				else {
				p2++;
				}
			}
				for (int i = count; i < n; i++) {
					if (arr[i] == 1) {
						sum++;
						if (answer < sum) {
							answer = sum;
						}
					} else {
						break;
					}
			}

			p2_n = 0;
			p1++;
			p1=zero;
			p2=zero;
			count=zero;
			sum = 0;
		}
		return answer;
	}

	public static void main(String[] args) {
		Twopointer06_1 T = new Twopointer06_1();
		Scanner kb = new Scanner(System.in);
		int n = kb.nextInt();
		int k = kb.nextInt();
		arr = new int[n];
		for (int i = 0; i < n; i++) {
			arr[i] = kb.nextInt();
		}
		System.out.println(T.solution(n, k));

	}

}

 

 

 

import java.util.Scanner;

public class Main {
	public int solution(int[] arr , int k) {
		int answer=0, tmp=0, lt=0, k2=k;
		
		for(int rt=0;rt<arr.length;rt++) {
			if(arr[rt]==1) {
				tmp++;
				answer=Math.max(tmp, answer);
			}else if(arr[rt]==0 && k!=0) {
				k--;
				tmp++;
				answer=Math.max(tmp, answer);
			}else if(k==0) {
				tmp=0;
				lt++;
				rt=lt;
				k=k2;
			}
		}
		
		return answer;
	}
	public static void main(String[] args) {
		Main T = new Main();
		Scanner kb = new Scanner(System.in);
		int n=kb.nextInt();
		int k=kb.nextInt();
		int[] arr = new int[n];
		for(int i=0;i<n;i++) {
			arr[i]=kb.nextInt();
		}
		System.out.println(T.solution(arr,k));
	}

}

 

 

+) 세련된 풀이

1. int answer=0, cnt=0, lt=0;
결과값, 카운트, 포인터 변수 정의
2. for(int rt=0;rt<n;rt++) {
포인터2는 n까지 반복하는데,
if(arr[rt]==0)
포인터2의 값이 0일경우 카운트를 증가시킨다.
while(cnt>m) {
변경가능한수 m보다 카운트가 크면 반복
if(arr[lt]==0)
포인터1의 값이 0이면 카운트에서 빼고,  포인터1의 값을 증가시킨다.

3. answer=Math.max(answer, rt-lt+1);

포인터2에서 포인터1을 빼고 +1한 값과 결과값을 비교해서 큰 값이 큰값

 

즉, 결과값은 0이고, rt-lt+1은, 포인터2의 값이 0인곳이 존재하면 cnt를 증가시키므로,

변경가능하다면, 포인터1의 값이 0이면 바꾸고, 카운트를 감소시킨다.

package twopointer.ch03;

import java.util.Scanner;

public class Twopointer06 {
	//# 최대 길이 연속 부분수열
	//0과 1로 구성된 길이가 N인 수열에서, 최대 k번 변경가능한데, 0을 1로 변경가능
	//최대 k번의 변경을 통해 1로만 구성된 최대 길이의 연속부분수열을 찾아라.
	
	public static void main(String[] args) {
		Twopointer06 T = new Twopointer06();
		Scanner kb = new Scanner(System.in);
		int n=kb.nextInt();
		int m=kb.nextInt();
		int[] arr=new int[n];
		for(int i=0;i<n;i++) {
			arr[i]=kb.nextInt();
		}
		System.out.println(T.solution(n,m,arr));
		kb.close();
	}
	public int solution(int n,int m,int[]arr) {
		//1.ds
		int answer=0, cnt=0, lt=0;
		//결과값, 카운트, 포인터 변수 정의
		
		//2.for, while
		for(int rt=0;rt<n;rt++) {
			//포인터2는 n까지 반복하는데,
			if(arr[rt]==0)
				cnt++;
			//포인터2의 값이 0일경우 카운트를 증가시킨다.
			
			while(cnt>m) {
				//변경가능한수 m보다 카운트가 크면 반복
				if(arr[lt]==0)
					cnt--;
				//포인터1의 값이 0이면 카운트에서 뺸다.
				lt++;
				//포인터1의 값을 증가시킨다.
			}
			answer=Math.max(answer, rt-lt+1);
			//포인터2에서 포인터1을 빼고 +1한 값과 결과값을 비교해서 큰 값이 큰값
			//결과값은 0이고, rt-lt+1은, 포인터2의 값이 0인곳이 존재하면 cnt를 증가시키므로, 변경가능하다면, 포인터1의 값이 0이면 바꾸고, 카운트를 감소시킨다.
		}
		return answer;
	}

}

1. 0-> 1로 바꿀 수 있는 K값을 줄이면서, 0보다 작아지면 while문 반복

2. 0일 때 cnt값을 늘리면서, k보다 커지면 while문 반복하면서 줄인다.

 

1. 0-> 1로 바꿀 수 있는 K값을 줄이면서, 0보다 작아지면 while문 반복

import java.util.Scanner;
  
public class Main {
  public static void main(String[] args){
    Scanner in=new Scanner(System.in);
    int n = in.nextInt();
    int k = in.nextInt();
    int[] arr = new int[n];
    for(int i=0;i<n;i++){
      arr[i]=in.nextInt();
    }
    int answer=0;
    int result=Integer.MIN_VALUE;
    //k번 0->1로 변경가능 
    int lt=0;
    int tmp=0;
    for(int rt=0;rt<n;rt++){
      if(arr[rt]==0) k--;
      while(k<0){
        if(arr[lt]==0) k++;
        lt++;
      }
      result=Math.max(rt-lt+1,result);
    }
    System.out.println(result);
  }
}

 

2. 0일 때 cnt값을 늘리면서, k보다 커지면 while문 반복하면서 줄인다.

import java.util.Scanner;
  
public class Main {
  public static void main(String[] args){
    Scanner in=new Scanner(System.in);
    int n = in.nextInt();
    int k = in.nextInt();
    int[] arr = new int[n];
    for(int i=0;i<n;i++){
      arr[i]=in.nextInt();
    }
    int answer=0;
    int result=Integer.MIN_VALUE;
    //k번 0->1로 변경가능 
    int lt=0;
    int cnt=0;
    for(int rt=0;rt<n;rt++) {
      //포인터2는 n까지 반복하는데,
      if(arr[rt]==0)
        cnt++;
      //포인터2의 값이 0일경우 카운트를 증가시킨다.

      while(cnt>k) {
        //변경가능한수 k보다 카운트가 크면 반복
        if(arr[lt]==0)
          cnt--;
        //포인터1의 값이 0이면 카운트에서 뺸다.
        lt++;
        //포인터1의 값을 증가시킨다.
      }
      answer=Math.max(answer, rt-lt+1);
      //포인터2에서 포인터1을 빼고 +1한 값과 결과값을 비교해서 큰 값이 큰값
      //결과값은 0이고, rt-lt+1은, 포인터2의 값이 0인곳이 존재하면 cnt를 증가시키므로, 변경가능하다면, 포인터1의 값이 0이면 바꾸고, 카운트를 감소시킨다.
    }
    System.out.println(answer);
  }
}

 

 


+)03.02

import java.util.Scanner;
import java.util.*;
  
public class Main {
  public static void main(String[] args){
    Scanner in=new Scanner(System.in);
    int n = in.nextInt();
    int m = in.nextInt();
    int[] arr = new int[n];
    for(int i=0;i<n;i++){
      arr[i]=in.nextInt();
    }
    Main main =new Main();
    System.out.println(main.solution(arr,m));
  }
  public int solution(int[] arr, int k){
    int lt=0;
    int cnt=0;
    int result=0;

    for(int i=0;i<arr.length;i++){
      if(arr[i]==0) {
        cnt++;
      }
      while(cnt>k){
        if(arr[lt]==0) cnt--;
        lt++;
      }
      result=Math.max(result, i-lt+1);
    }

    return result;
  }
}
728x90
반응형