Algorithm/백준

Backjoon(백준) 2470- 두 용액 (Java)

GrapeMilk 2020. 5. 6. 23:08

문제링크

 ( https://www.acmicpc.net/problem/2470 )

분류 

 - TwoPointers Algorithm

1. 풀이 힌트

 - 주어진 용액들을 오름차순으로 정렬한 뒤, 양쪽 끝에 포인터를 두어 두 용액의 합이 0보다 크면 오른쪽 포인터를 왼쪽으로 한칸, 0보다 작으면 왼쪽 포인터를 오른쪽으로 한칸 옮기면서 두 포인터가 만날때 까지 각각의 합을 구하고, 도출된 합 중에서 0과 가장 가까운 결과에 해당하는 포인터가 지목하는 용액의 값을 오름차순으로 출력하면 된다.

2. 풀이 과정

1) 밑과 같이 각 용액이 주어졌을 때 먼저 오름차순으로 정렬한다

-2 4 -99 -1 98

2) 오름차순으로 정렬된 용액들

-99 -2 -1 4 98

3) 양쪽 끝에 포인터를 둔다

 - 왼쪽 끝의 포인터는 파랑색으로 표현, 오른쪽 포인터는 빨간색으로 표현

-99 -2 -1 4 98

4) 각 포인터가 위치한 두 용액의 합을 구한다

 - 포인터가 양 끝에 위치하므로 두 용액의 합을 구하면 -1이 나온다(-99 + 98) 

 

5) 포인터에 위치한 두 용액 합의 결과가 마이너스이면 왼쪽(파란색) 포인터를 오른쪽으로 한칸 옮긴다.

 - 두 용액의 합이 마이너스가 나왔다는 뜻은 두 용액의 값중 마이너스 용액의 값이 크다는 뜻이므로 좀 더 작은 마이너스를 가진 용액으로 포인터를 옮기기위해 왼쪽 포인터를 오른쪽으로 한칸 옮기는 것이다.

-99 -2 -1 4 98

6) 포인터를 옮겼으면, 두 포인터가 가르키는 두 용액의 합을 구한다

 - 결과는 96으로 이번에는 두 용액 합이 플러스가 됐다. 플러스 일때는 오른쪽(빨간색) 포인터를 왼쪽으로 한 칸 옮긴다.

 

7) 과정 반복

 - 두 포인터가 만날 때 까지 위와 같은 과정을 반복하고, 각 과정을 시행하면서 나온 두 용액의 합은 따로 하나의 배열에 저장한다.

 

8) 배열에 저장된 값중에 0과 가장 가까운 값을 나타내는 두 용액이 정답이된다.

2. 풀이 과정

3. 코드 풀이 (Java)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class TwoSolutions {

    public static void main(String[] args) throws IOException {
        
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        int[] arr = new int[n]; // 용액들을 저장할 배열
        int[] dp = new int[n - 1]; // 두 용액의 합을 저장할 배열
        
        StringTokenizer st = new StringTokenizer(br.readLine());
        
        for (int i = 0; i < n; i++) { // 용액 저장
            arr[i] = Integer.parseInt(st.nextToken());
        }
        
        Arrays.sort(arr); // 오름차순으로 정렬
           
        int pL = 0; // 왼쪽 포인터
        int pR = n - 1; // 오른쪽 포인터
        
        int result = arr[pL] + arr[pR]; // 0과 가장 가까운 값을 비교하기 위한 변수 선언
        int resultPL = arr[pL]; // 0과 가장 가까운 값을 이루고 있는 용액 1
        int resultPR = arr[pR]; // 0과 가장 가까운 값을 이루는 용액 2
        
        for (int i = 0; i < n - 1; i++) {
            dp[i] = arr[pL] + arr[pR]; 
  
            if (Math.abs(dp[i]) < Math.abs(result)) { // 결과값 최신화
                result = dp[i];
                resultPL = arr[pL];
                resultPR = arr[pR];
            }
            // 두 용액 합의 결과에 따라 포인터 이동
            if (dp[i] > 0) { 
                pR--;
            } else if (dp[i] < 0) {
                pL++;
            } else { // 두 용액의 합이 0이면 for문을 종료
                break;
            }  
        }
        // 결과 출력
        System.out.println(resultPL + " " + resultPR);

    }

}