본문 바로가기

Dot Algo∙ DS/PS

[BOJ] 백준 1912번 연속합 (Java)

    #1912 연속합

    난이도 : 실버 2

    유형 : DP

     

    1912번: 연속합

    첫째 줄에 정수 n(1 ≤ n ≤ 100,000)이 주어지고 둘째 줄에는 n개의 정수로 이루어진 수열이 주어진다. 수는 -1,000보다 크거나 같고, 1,000보다 작거나 같은 정수이다.

    www.acmicpc.net

    ▸ 문제

    n개의 정수로 이루어진 임의의 수열이 주어진다. 우리는 이 중 연속된 몇 개의 수를 선택해서 구할 수 있는 합 중 가장 큰 합을 구하려고 한다. 단, 수는 한 개 이상 선택해야 한다.

    예를 들어서 10, -4, 3, 1, 5, 6, -35, 12, 21, -1 이라는 수열이 주어졌다고 하자. 여기서 정답은 12+21인 33이 정답이 된다.

     입력

    첫째 줄에 정수 n(1 ≤ n ≤ 100,000)이 주어지고 둘째 줄에는 n개의 정수로 이루어진 수열이 주어진다. 수는 -1,000보다 크거나 같고, 1,000보다 작거나 같은 정수이다.

     출력

    첫째 줄에 답을 출력한다.

     

    문제 풀이  

    연속 부분 구간 합 문제는 종만북에서도 한 번 다룬 문제이다. 왜냐하면 잘못 접근하면 O(N^3)이 되고 잘 설계하면 O(N)이 될 수 있기 때문이다.

     

    구상

    0번 인덱스부터 n-1인덱스까지 순차적으로 탐색하면서 합을 구해준다. 그런데 만약 이전 값이 음수라면 앞에 아무리 큰 수가 있더하더라도 더하는 것은 무의미하다. 차라리 앞의 큰 수 하나만 계산하는 것이 더 큰 값을 얻을 수 있다.

     

    설계

    1. 이전 값이(cur)이 0보다 작으면 연속합을 현재 값으로 새로 갱신한다.cur = Math.max(0, cur) + num;
    2. 최대 연속 합이 갱신되는지 매번 체크해준다. max = Math.max(max, cur)

     

    풀이 코드

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.StringTokenizer;
    
    public class Main {
    
    	public static void main(String[] args) throws IOException{
    		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    		int n = Integer.parseInt(br.readLine());
            
    		StringTokenizer st = new StringTokenizer(br.readLine());
    		int cur =Integer.parseInt(st.nextToken());
    		int max =cur;
    		for(int i=1; i<n; i++) {
    			int num = Integer.parseInt(st.nextToken());
    			cur = Math.max(0, cur) + num;
    			max = Math.max(max, cur);
    		}
    		System.out.println(max);
    	}
    }

     

     

    잘못 접근한 예

    이렇게 매번 새롭게 연속합을 계산해서 최댓값을 구하면 O(n^3)으로 시간초과가 발생한다.

    int[] arr = new int[n];
    for(int i=0; i<n; i++) {
    	arr[i] = Integer.parseInt(st.nextToken());
    }
    
    int max = arr[0];
    for(int i=0; i<n; i++) {
    	for(int j=i; j<n; j++) {
    		int sum=0;
    		for(int k=i; k<=j; k++) {
    			sum += arr[k];
    		}
    		max = Math.max(max, sum);
    	}
    }
    
    System.out.println(max);