본문 바로가기
백준_JAVA

[백준] 3273번 - 두 수의 합

by stonage 2023. 5. 29.

 

 

3273번: 두 수의 합

n개의 서로 다른 양의 정수 a1, a2, ..., an으로 이루어진 수열이 있다. ai의 값은 1보다 크거나 같고, 1000000보다 작거나 같은 자연수이다. 자연수 x가 주어졌을 때, ai + aj = x (1 ≤ i < j ≤ n)을 만족하는

www.acmicpc.net

 

 

 

 

문제

n개의 정수로 이루어진 수열에서 수열의 요소인 Ai, Aj와 그외 주어지는 자연수 x에 대하여 Ai + Aj = x를 만족하는 (Ai, Aj)의 쌍의 갯수를 구하시오.

 

 

 

조건

수열의 요소를 Ai라고 할때 1 <= Ai <= 1,000,000

두 요소의 합인 x에 대해 1 <= x <= 2,000,000

수열의 크기 n에 대해 1 <= n <= 100,000

 

 

 

 

풀이 방향

두 요소 Ai와 Aj의 합은 다음과 같은 세 가지 경우에 속한다. (Ai < Aj 라고 가정)

i) Ai + Aj < x

ii) Ai + Aj == x

iii) Ai + Aj > x

 

이 문제의 경우 수열의 구성하는 수들 중에서 단 두 개의 수만을 골라 그 합이 x와 같은지 비교해봐야 한다. 따라서 가장 먼저 가장 작은 요소와 가장 큰 요소의 합을 x와 비교하여 위 세 경우 중 어디에 속하는지에 따라 진행을 달리한다. 

 

case i)

현재 Aj는 수열에서 가장 큰 수이기 때문에 Ai는 어떠한 수와도 조건을 만족시키지 못한다. 따라서 i)의 경우에는 Ai 그 다음으로 큰 수와 Aj의 조합을 비교해본다. 

 

case ii) 

Ai + Aj == x라는 조건에 부합하므로 출력할 변수에 1을 더하고 두 번째로 작은 수와 두 번째로 큰 수가 조건에 부합하는지 확인한다.

 

case iii)

현재 Ai 는 가장 작은 수 이기 때문에 Aj는 어떤 수와도 조건을 만족시키지 못한다. 따라서 Ai와 그 다음으로 큰 수에 대해서 판단한다.

 

 

위 과정을 Ai == Aj가 되면 반복을 종료하는데, 조건에 의하면 반드시 수열 내 두 개 요소의 조합만이 답이 될 수 있기 때문이다.

 

또한 위 세 가지 경우는 언제나 현재 가장 작은 요소와 현재 가장 큰 요소간의 합을 비교한다. 따라서 사전에 해당 수열을 정렬시켜두어야 한다.

 

int left = 0; // 가장 작은 요소의 인덱스
int right = arr.length - 1; // 가장 큰 요소의 인덱스
int count = 0; // 출력할 갯수

while (left < right) {

    int sum = arr[left] + arr[right];
	
    // 조건에 부합하는 경우
    if (sum == x) {
        count++;
        left++;
        right--;
    }
    
    //두 수의 합계가 x보다 크다면 현재 가장 큰 수인 arr[right]은 어떠한 경우에도 조건에 부합할 수 없다. 따라서 그 다음으로 큰 수를 비교
    else if (sum > x) 
        right--;
        
    // 두 수의 합계가 x보다 작다면 현재 가장 작은 수인 arr[left]는 어떠한 경우에도 조건에 부합할 수 없다. 따라서 그 다음으로 작은 수를 비교
    else 
        left++;
}

 

 

 

 

 

 

전체 코드

import java.util.*;

public class Main {
    public static void main (String[] args) {
        
        Scanner sc = new Scanner(System.in);
        
        int n = Integer.parseInt(sc.nextLine());
        int[] arr = new int[n];
        
        String[] input = sc.nextLine().split(" ");
        for (int i=0; i<n; i++) 
            arr[i] = Integer.parseInt(input[i]);
        
        Arrays.sort(arr);
        
        int x = Integer.parseInt(sc.nextLine());
        
        int left = 0;
        int right = arr.length - 1;
        int count = 0;
        while (left < right) {
            
            int sum = arr[left] + arr[right];
            
            if (sum == x) {
                count++;
                left++;
                right--;
            }
            else if (sum > x) 
                right--;
            else 
                left++;
        }
        
        
        System.out.println(count);
        
        sc.close();
    }
}

 

 

'백준_JAVA' 카테고리의 다른 글

[백준] 11659번 - 구간 합 구하기 4  (1) 2023.05.30
[백준] 2447번 - 별 찍기 - 10  (0) 2023.05.29
[백준] 1976번 - 여행 가자  (0) 2023.05.27
[백준] 1991번 - 트리 순회  (0) 2023.05.25
[백준] 6497번 - 전력난  (0) 2023.05.24