백준

[백준_9024번] 두 수의 합

빙수빈수 2022. 2. 10. 15:47

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

 

9024번: 두 수의 합

프로그램은 표준입력으로 입력을 받는다. 프로그램 입력은 t 개의 테스트 케이스로 구성된다. 입력의 첫 번째 줄에 테스트 케이스의 개수를 나타내는 정수 t 가 주어진다. 두 번째 줄부터 두 줄

www.acmicpc.net

[문제]

 여러 개의 서로 다른 정수 S = {a1, a2, …, an} 와 또 다른 정수 K 가 주어졌을 때, S 에 속하는 서로 다른 두 개의 정수의 합이 K 에 가장 가까운 두 정수를 구하시오. 예를 들어, 10 개의 정수

 

S = { -7, 9, 2, -4, 12, 1, 5, -3, -2, 0}

 

가 주어졌을 때, K = 8 에 그 합이 가장 가까운 두 정수는 {12, -4} 이다. 또한 K = 4 에 그 합이 가장 가까운 두 정수는 {-7, 12}, {9, -4}, {5, -2}, {5, 0}, {1, 2} 등의 다섯 종류가 있다.

여러 개의 서로 다른 정수가 주어졌을 때, 주어진 정수들 중에서 서로 다른 두 정수의 합이 주어진 또 다른 정수에 가장 가까운 두 정수의 조합의 수를 계산하는 프로그램을 작성하시오.

 

[입력 조건]

 프로그램은 표준입력으로 입력을 받는다. 프로그램 입력은 t 개의 테스트 케이스로 구성된다. 입력의 첫 번째 줄에 테스트 케이스의 개수를 나타내는 정수 t 가 주어진다. 두 번째 줄부터 두 줄에 한 개의 테스트 케이스에 해당하는 데이터가 주어진다. 각 테스트 케이스의 첫 번째 줄에는 두 개의 정수 n 과 K (2 ≤ n ≤ 1,000,000, -108 ≤ K ≤ 108 )가 한 개의 공백을 사이에 두고 입력된다. 두 번째 줄에는 n 개의 정수가 하나의 공백을 사이에 두고 주어지며, 각 정수의 최댓값은 108 이고, 최솟값은 -108 이다. 잘못된 데이터가 입력되는 경우는 없다.

 

[코드]

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

public class BaekJoon_9024 {
	static int n,k,min;
	static int[] num;
	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st;
		
		int t=Integer.parseInt(br.readLine());
		
		while(t-->0) {
			st=new StringTokenizer(br.readLine());
			
			n=Integer.parseInt(st.nextToken());
			k=Integer.parseInt(st.nextToken());
			min=Integer.MAX_VALUE;
			num=new int[n];
			
			st=new StringTokenizer(br.readLine());
			for(int i=0;i<n;i++) 
				num[i]=Integer.parseInt(st.nextToken());
			
			Arrays.sort(num);
			
			System.out.println(Two_Pointer());
		}
	}
	
	static int Two_Pointer() {
		int left=0;
		int right=n-1;
		
		int count=0;
		while(left<right) {
			int sum=num[left]+num[right]; // 두 수의 합
			
			if(sum>=k) // 합이 k보다 크다면 큰 수 빼기 -> right--
				right--;
			
			else // 합이 k보다 작으면 더 큰 수 더하기 -> left++
				left++;
			
			/*
			 * min은 k와 k와 가까운 수의 차가 저장된 변수
			 * min이 갱신될 때 마다 k와 가까운 수의 개수를 구하는 count 초기화 
			 */
			if(Math.abs(k-sum)<min) {
				min=Math.abs(k-sum);
				count=1;
			}
			// k와 가까운 정수를 발견하면 count 증가
			else if(Math.abs(k-sum)==min)
				count++;
		}
		
		return count;
	}
}

 

[고찰]

 이번 문제는 투포인터를 사용하는 문제였다. 수열 저장한 배열을 오름차순으로 정렬한 후 배열의 맨 처음을 가리키는 left와 맨 끝을 가리키는 right의 합을 구해 k 값과 비교해야 한다. 이때 주의할 점은 두 수의 합이 k인 경우를 구하는 것이 아니라 k와 가까운 값이 나오는 경우의 수를 구하는 것이다. 

 따라서 k와 두 수를 더한 값을 뺀 값을 min에 저장하고 더 작은 min 값을 찾을 때 마다 여태까지 k 값과 가까운 값을 count 한 변수를 초기화 해주어야 한다.이 점만 주의한다면 쉽게 해결할 수 있는 문제였다. 

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

[백준_1644번] 소수의 연속합  (0) 2022.02.11
[백준_15961번] 회전 초밥  (2) 2022.02.11
[백준_1744번] 수 묶기  (0) 2022.02.10
[백준_2075번] N번째 큰 수  (0) 2022.02.08
[백준_1202번] 보석 도둑  (0) 2022.01.19