ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준 2473번] 세 용액 (Java 풀이)
    Algorithm/정렬(Sort) 2022. 5. 6. 20:27

    백준알고리즘 2473번 : 세 용액 (Solved.ac 난이도 Gold4)

     

    https://www.acmicpc.net/problem/2473

     

    2473번: 세 용액

    첫째 줄에는 전체 용액의 수 N이 입력된다. N은 3 이상 5,000 이하의 정수이다. 둘째 줄에는 용액의 특성값을 나타내는 N개의 정수가 빈칸을 사이에 두고 주어진다. 이 수들은 모두 -1,000,000,000 이상

    www.acmicpc.net

     

     

    숫자 3개를 선택하여 가장 절대값이 가장 작은 숫자를 만드는 조합을 출력하는 문제이다.

    두개라면 two pointer를 사용하여 풀 수 있을꺼라 생각하였는데,

    고민하다가 하나를 고정하는 대신 나머지 2개를 투 포인터로 fix하는 방법은 어떨까 생각해보았다.

    물론 내가 작성한 logic은 중복으로 탐색하는 경우가 충분히 발생할수 있다.


    숫자 하나를 fix하는 것을 제외하고는 투 포인터와 다르지 않다.

    다만 fix하는 숫자의 위치를 for문을 한번 돌면서 바꿔줄 것이기 때문에,

    각 포인터들은 fix하는 숫자가 있는 index는 타지 않도록 충분한 조건을 걸어주었다.

    당연하지만, 이렇게 해야 fix하는 숫자와 포인터 2개로 총 3개의 서로 다른 숫자를 뽑아줄 수 있다.

     

     

    풀이 과정


    1. 숫자를 배열으로 받은 뒤 오름차순으로 정렬한다.

    2. 첫번째 index와 마지막 index가 모두 양수거나 모두 음수인 case는 0,1,2 혹은
        arr.length-3,-2,-1을 출력해주면 되므로 if문으로 배제해준다.

    3. 2번의 case가 아닌경우, two pointer를 사용한다.
    3-1. for문을 돌면서 고정할 숫자를 지정해주며,
          포인터들은 고정 숫자의 index를 피하면서 돌 수 있도록 조건문을 설정해준다.
    3-2. fix값을 포함한 투 포인터 값의 합의 절대값이 기존 절대값보다 작다면, 숫자 조합을 바꿔준다.
    3-3. 최종적으로 남은 숫자 목록을 오름차순으로 출력한다.

     

     

    소스 ▽

    더보기
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.Arrays;
    import java.util.StringTokenizer;
    
    public class Main { // [Gold4] 2473번 : 세 용액
        public static void main(String[] args) throws IOException {
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            int num = Integer.parseInt(br.readLine());
            StringTokenizer st = new StringTokenizer(br.readLine());
    
            long[] arr = new long[num];
            for (int i = 0; i < num; i++) {
                arr[i] = Long.parseLong(st.nextToken());
            }
            Arrays.sort(arr);
            long min = 3000000001L;
            long fix = 0;
            long ans[] = new long[3];
            if (arr[0] * arr[arr.length - 1] > 0) {//좌우 모두 음수일때/좌우 모두 양수일때 -> 앞 if문에서 제거
                if (arr[0] > 0) {
                    System.out.println(arr[0] + " " +arr[1]+ " " + arr[2]);
                } else {
                    System.out.println(arr[arr.length - 3]+ " " + arr[arr.length - 2]+ " " + arr[arr.length - 1]);
                }
            } else {//좌측끝은 음수, 우측 끝은 양수일때
                stop:
                for (int i = 0; i < num; i++) {
                    fix = arr[i];
                    int x = i != 0 ? 0 : 1;
                    int y = i == num - 1 ? num - 2 : num - 1;
                    while (x < num && y >= 0 && x < y) {
                        if (Math.abs(arr[x] + arr[y] + fix) < Math.abs(min)) {
                            min = arr[x] + arr[y] + fix;
                            ans[0] = fix;
                            ans[1] = arr[x];
                            ans[2] = arr[y];
                        }
                        if (arr[x] + arr[y] + fix > 0) {
                            y--;
                            if (y == i) {
                                y--;
                            }
                        } else if (arr[x] + arr[y] + fix < 0) {
                            x++;
                            if (x == i) {
                                x++;
                            }
                        } else {
                            break stop;
                        }
                    }
                }
                Arrays.sort(ans);
                for (int i = 0; i < 3; i++) {
                    System.out.print(ans[i] + " ");
                }
            }
    
        }
    }

     

     

    댓글

Designed by Tistory.