[백준, BOJ 9024] 두 수의 합 (java)
Problem Solving/BOJ

[백준, BOJ 9024] 두 수의 합 (java)

728x90

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

메모리: 231,292 KB , 시간: 2,072 ms

사용 알고리즘: 정렬, 이분 탐색, 두 포인터

728x90

처음엔 TreeSet으로 K - arr[i]에 해당하는 수가 있는지(contains) 검사하고,

없다면 큰 수 중 가장 작은 수(higher)와 작은 수 중 가장 큰 수(lower)를 검사해서 구했었다.

-> 메모리 초과

 

그다음 이분 탐색으로 K - arr[i]보다 작은 수 중 가장 큰 수를 구하고, 이분 탐색으로 구한 수와 그 수보다 큰 수 중 가장 작은 수를 비교하여 구했다.

정답은 뜨는데, 주석 쓰고 다시 돌렸더니 메모리 초과... 같은 코드 다시 돌렸는데 또 정답

약간 불안 불안한 듯.. 문제 풀고 투 포인터로 풀 수 있다는 거 알고 투 포인터로도 풀었다.

 

투 포인터는 코드짜기 제일 쉽고 깨끗한데 제일 안정적으로 정답 뜬다.

왜 투 포인터 생각을 못했지?

 

이분 탐색

메모리: 276,896 KB , 시간: 2,264 ms

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;
public class Main {
static int n, K;
static int[] arr;
public static void main(String[] args) throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
StringBuilder answer = new StringBuilder();
int t = Integer.parseInt(br.readLine());
for (int tc = 0; tc < t; tc++) {
st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken());
K = Integer.parseInt(st.nextToken());
arr = new int[n];
st = new StringTokenizer(br.readLine());
for (int i = 0; i < n; i++) {
arr[i] = Integer.parseInt(st.nextToken());
}
// 정렬
Arrays.sort(arr);
int min = Integer.MAX_VALUE;
int result =0;
int[] ret;
for (int i = 0; i < n - 1; i++) {
// 이분탐색으로
ret = getMinSub(i, i + 1, n - 1);
if(min > ret[0]) {
min = ret[0];
result = ret[1];
}
else if(min == ret[0]) {
result += ret[1];
}
}
answer.append(result + "\n");
}
System.out.print(answer);
}
// start부터 end까지 index와의 합이 K와 가장 가까운 수의 차 구하기
private static int[] getMinSub(int index, int start, int end) {
int[] ret = new int[2];
ret[0] = Integer.MAX_VALUE;
// 찾고자 하는 수
int find = K - arr[index];
int mid, get = start;
while(start <= end) {
mid = (start + end) / 2;
if(arr[mid] > find) end = mid - 1;
else {
get = mid;
start = mid + 1;
}
}
// 찾은 수
int sub = Math.abs(K - (arr[index] + arr[get]));
if(ret[0] > sub) {
ret[0] = sub;
ret[1] = 1;
}
else if(ret[0] == sub) {
ret[1]++;
}
// 찾은 수보다 더 큰 수 중 가장 작은 수도 검사
if(get != n - 1) {
sub = Math.abs(K - (arr[index] + arr[get + 1]));
if(ret[0] > sub) {
ret[0] = sub;
ret[1] = 1;
}
else if(ret[0] == sub) {
ret[1]++;
}
}
return ret;
}
}

투 포인터

메모리: 231,292 KB , 시간: 2,072 ms

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
StringBuilder answer = new StringBuilder();
int t = Integer.parseInt(br.readLine());
int n, K;
int[] arr;
for (int tc = 0; tc < t; tc++) {
st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken());
K = Integer.parseInt(st.nextToken());
arr = new int[n];
st = new StringTokenizer(br.readLine());
for (int i = 0; i < n; i++) {
arr[i] = Integer.parseInt(st.nextToken());
}
// 정렬
Arrays.sort(arr);
int min = Integer.MAX_VALUE;
int result = 0;
int start = 0, end = n - 1;
int sub;
while(start < end) {
sub = Math.abs(K - (arr[start] + arr[end]));
if(min > sub) { // 차가 더 작은 조합 찾음
min = sub;
result = 1;
}
else if (min == sub) { // 가장 작은 차 조합 하나 더 찾음
result++;
}
if(arr[start] + arr[end] < K) { // K보다 작으면 더 크게
start++;
}
// K보다 크면 더 작게
else end--;
}
answer.append(result + "\n");
}
System.out.print(answer);
}
}
728x90