jusung-c
으 하기싫어
jusung-c
  • 공부 기록 (96)
    • Spring (42)
      • Spring 기초 이론 (8)
      • Spring 핵심 원리 - 기본 (9)
      • Blog 만들기 with SpringBoot (25)
    • JAVA (7)
      • Java 문법 (2)
      • 객체지향의 사실과 오해 (5)
    • Algorithm (47)
      • 자료구조 (3)
      • 완전탐색 (22)
      • 정렬 (4)
      • 이분탐색 (12)
      • 투 포인터 (4)
hELLO · Designed By 정상우.
jusung-c

으 하기싫어

Algorithm/투 포인터

BOJ 2230 - 수 고르기

2022. 6. 7. 16:16

 

 

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

 

2230번: 수 고르기

N개의 정수로 이루어진 수열 A[1], A[2], …, A[N]이 있다. 이 수열에서 두 수를 골랐을 때(같은 수일 수도 있다), 그 차이가 M 이상이면서 제일 작은 경우를 구하는 프로그램을 작성하시오. 예를 들어

www.acmicpc.net

 

 

  • N개의 정수로 이루어진 수열 A (1 ≤ N ≤ 10만)
  • 수열 A의 각 원소는 (0 ≤ |A[i]| ≤ 10억)
  • 두 수를 골랐을 때(같은 수일 수도 있다), 그 차이가 M 이상이면서 제일 작은 경우 (0 ≤ M ≤ 20억)

 

아이디어

배열 A에서 두 수를 골라서 차이가 M 이상인 경우를 찾기 위해 먼저 모든 경우의 수를 생각해 봤다. 

배열 A를 오름차순 정렬 후 이중 for문으로 모든 차이를 구해서 가장 작은 차이를 갱신하면 답을 구할 수 있다.

 

for (int i = 1; i <= N; i++) {
    for (int j = i; j <= N; j++) {
        if (A[j] - A[i] >= M) {
            ans = Math.min(ans, A[j] - A[i]);
            break;
        }
    }
}

 

이렇게 하면 풀리기는 풀리지만 시간이 오래 걸린다. 

 

더 빠르게 풀기 위해 A 배열을 오름차순으로 정렬한 후 Left와 Right 투 포인터를 활용하여 A[Right]와 A[Left]의 차이 비교해준다.

  • A[Right]와 A[Left] 차이를 비교했을 때 M보다 작으면 고려할 대상이 아니므로 R++로 넘어간다. 
  • 차이가 M이상인 경우 ans를 갱신해준 후 L++로 다음 경우로 넘어간다.
ans = Integer.MAX_VALUE;
int R = 1;

for (int L = 1; L <= N; L++) {

    // 필요한 만큼 R 이동
    while (R + 1 <= N) {
        // M 이하인 경우는 R을 이동시켜서 건너뛰기
        if (A[R] - A[L] < M) {
            R++;
        // M 이상일 경우 정답갱신하러 ㄱㄱ
        } else {
            break;
        }
    }

    // 정답 갱신
    // 현재 R 포인터의 뒤쪽은 어짜피 차이가 커질테니 상관 X
    if (A[R] - A[L] >= M) {
        ans = Math.min(ans, A[R] - A[L]);
    }

}

 

이렇게 하면 훨씬 빠른 속도로 적은 경우의 수만 고려해서 풀 수 있다. 

 

구현

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

public class Main {
    static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
    static int N, M, ans;
    static int[] A;

    static void init() throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        StringTokenizer st = new StringTokenizer(br.readLine(), " ");
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());

        A = new int[N + 1];
        for (int i = 1; i <= N; i++) {
            A[i] = Integer.parseInt(br.readLine());
        }
    }

    static void pro() throws IOException {
        Arrays.sort(A, 1, N+1);

        ans = Integer.MAX_VALUE;
        int R = 1;

        for (int L = 1; L <= N; L++) {

            // 필요한 만큼 R 이동
            while (R + 1 <= N) {
                // M 이하인 경우는 R을 이동시켜서 건너뛰기
                if (A[R] - A[L] < M) {
                    R++;
                // M 이상일 경우 정답갱신하러 ㄱㄱ
                } else {
                    break;
                }
            }

            // 정답 갱신
            // 현재 R 포인터의 뒤쪽은 어짜피 차이가 커질테니 상관 X
            if (A[R] - A[L] >= M) {
                ans = Math.min(ans, A[R] - A[L]);
            }

        }

        bw.write(ans+" ");
    }

    public static void main(String[] args) throws IOException {
        init();

        pro();

        bw.close();
    }

}

 

 

 

 

 

 

 

 

 

 

저작자표시 비영리 변경금지

'Algorithm > 투 포인터' 카테고리의 다른 글

BOJ 2470 - 두 용액 (투 포인터)  (0) 2022.06.09
BOJ 15565 - 귀여운 라이언  (0) 2022.05.19
[Algorithm] Two Pointers  (0) 2022.05.16
    'Algorithm/투 포인터' 카테고리의 다른 글
    • BOJ 2470 - 두 용액 (투 포인터)
    • BOJ 15565 - 귀여운 라이언
    • [Algorithm] Two Pointers
    jusung-c
    jusung-c

    티스토리툴바