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
'Problem Solving > BOJ' 카테고리의 다른 글
[백준, BOJ 13414] 수강신청 (java) (0) | 2024.08.20 |
---|---|
[백준, BOJ 14950] 정복자 (java) (0) | 2024.07.29 |
[백준, BOJ 2058] 원자의 에너지 (java) (3) | 2024.07.25 |
[백준, BOJ 13424] 비밀 모임 (java) (0) | 2024.07.04 |
[백준, BOJ 20168] 골목 대장 호석 - 기능성 (java) (0) | 2024.07.03 |