코딩테스트/SWEA_Java

Q. 5642. 합(D3)

Ski_ 2023. 5. 17. 12:22

Q. 5642. 합(D3)

 

0. 문제

 

D3 난이도의 문제이고, DP를 이용한 문제이다.

수열이 주어지고 연속해서 원소를 골라 합을 구할 때, 그 합의 최대가 몇인지 구하는 프로그램을 작성하는 문제이다


1. 풀이

 

두 가지의 풀이 방법이 생각났다.

첫번재는 DP를 이용한 풀이이고, 두 번째는 투 포인터를 이용한 풀이이다.

 

1-1 DP를 이용한 풀이

DP인 경우 보통 정답이 dp[N - 1]인데, 이 문제의 경우는 그렇게는 정답을 구할 수 없어서 조금 시간이 걸렸다.

 

아래와 같은 방식으로 풀었다.

1) 반복문을 N-1까지 돌면서, 현재 인덱스의 숫자와 이전에 저장된dp + 현재 인덱스의 숫자를 비교해 큰 값을 dp에 저장한다.

2) dp 배열에 저장된 값 중 최대값을 저장한다.

 

코드는 아래와 같다.

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Deque;
import java.util.LinkedList;
import java.util.StringTokenizer;
 
public class Solution {
 
    static BufferedReader br;
    static StringBuffer sb = new StringBuffer();
    static StringTokenizer st;
     
 
    static int N;
    static int[] inputArr;
    static int[] dp;
     
    static void input() throws IOException {
        N = Integer.parseInt(br.readLine());
        inputArr = new int[N];
        st = new StringTokenizer(br.readLine());
        for (int i = 0; i < N; i++) inputArr[i] = Integer.parseInt(st.nextToken());
        dp = new int[N];
    }
     
    static void pro(int tc) throws Exception{
         
        dp[0] = inputArr[0];
        int max = inputArr[0];;
        for (int i = 1; i < N; i++) {
            dp[i] = Math.max(dp[i - 1] + inputArr[i], inputArr[i]);
            max = Math.max(dp[i],  max);
        }
         
        sb.append(String.format("#%d %d\n", tc, max));
    }
     
    public static void main(String[] args) throws Exception{
         
        br = new BufferedReader(new InputStreamReader(System.in));
        //br = new BufferedReader(new InputStreamReader(new FileInputStream("res/input.txt")));
         
        int T = Integer.parseInt(br.readLine());
        for(int tc = 1; tc <= T; tc++) {
            input();
            pro(tc);
        }
        System.out.println(sb);
         
    }
 
}

1-2 투 포인터를 이용한 풀이

 

투 포인터는 간단히 요약하면 두 개의 변수를 이용해 필요한 부분만 필요한 만큼 탐색하는 방식이다.

핵심은 두 개의 변수이고, 보통 두 변수가 모두 탐색하는데 O(2N)의 시간복잡도를 가진다.

 

아래와 같은 방식으로 풀었다.

1) L과 R을 선언하고, N까지 반복하며 각 원소들의 합을 저장한다.

2) 이 때 원소들의 합이 0보다 작을 경우 sum을 0으로 초기화하며, 원소들의 합을 저장할 때 마다 최대값을 저장한다.

3) R이 끝까지 도달하면 종료한다.

 

코드는 아래와 같다.

import java.io.*;
import java.util.StringTokenizer;

class Solution {


    static StringBuilder sb = new StringBuilder();
    static BufferedReader br;
    static StringTokenizer st;


    static int N;
    static int[] inputArr;

    static void input() throws IOException {
        N = Integer.parseInt(br.readLine());
        inputArr = new int[N];
        st = new StringTokenizer(br.readLine());
        for (int i = 0; i < N; i++) inputArr[i] = Integer.parseInt(st.nextToken());
    }

    static void pro(int tc) throws Exception{

        int R = 0, L = 0;
        int sum = 0;
        int max = inputArr[0];

        while(R < N) {
            sum += inputArr[R];
            max = Math.max(max, sum);

            if(sum < 0) {
                L = ++R;
                sum = 0;
            }else R++;
        }
        sb.append(String.format("#%d %d\n", tc, max));
    }

    public static void main(String[] args) throws Exception{

        br = new BufferedReader(new InputStreamReader(System.in));
//        br = new BufferedReader(new InputStreamReader(new FileInputStream("res/input.txt")));

        int T = Integer.parseInt(br.readLine());
        for(int tc = 1; tc <= T; tc++) {
            input();
            pro(tc);
        }
        System.out.println(sb);

    }

}

2. 시간복잡도 계산

 

0) N의 최대값은 100000이다.

1) 입력값 저장 - O(N)

2) dp, 투 포인터 - O(N)

따라서 두 풀이 모두 시간복잡도는 O(N)이고, 시간제한은 2초이므로 1초 이내에 풀 수 있다.

반응형