baekjoon
백준 2473번 : 세 용액 [자바]
Meluu_
2025. 5. 29. 10:09
🧫 문제 분석
✔️ 출처
📖 문제

기존 두 용액 문제에서
전체를 투포인터로 두고 투 포인터를 제외한 곳을 이분탐색으로 해서 풀려했으나
당연히 모든 용액이 3가지씩 조합되지 않기에 계속해서 틀렸다.
나의 약한 부분중 하나가 이런 부분인 것 같다.
꼭 3개이상 , 여러개 등 조합해야하는 문제나 비슷한 문제들을 만나면
하나를 고정하고 푼다는 이런 생각을 떠올리지 못한다.
까먹지 않기위해 블로그에 박제한다.
그리고 기껏 long type으로 계산해야한다고 메모해놓고 또 (long)으로 캐스팅안해서 틀렸다...
🔅 풀이 시도
import java.io.*;
import java.util.*;
public class Main {
static int[] solutions;
static int[] answer;
static long min;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringBuilder sb = new StringBuilder();
int n = Integer.parseInt(br.readLine());
solutions = new int[n];
StringTokenizer st = new StringTokenizer(br.readLine());
// 용액 특성값 초기화
for (int i = 0; i < n; i++) {
solutions[i] = Integer.parseInt(st.nextToken());
}
// 특성값을 오름차순 정렬
Arrays.sort(solutions);
answer = new int[3];
min = Long.MAX_VALUE;
// 투포인터 + 이분탐색
int left = 0, right = n - 1;
while (left <= right) {
// 먼저 두개의 용액을 섞는다.
int sum = solutions[left] + solutions[right];
addThirdSolution(left, right, sum); // 0에 가깝게 만들어주는 3번째 용액을 찾는다.
if (sum < 0) left++;
else right--;
}
for (int val : answer) {
sb.append(val).append(" ");
}
System.out.println(sb.toString());
}
// 0에 가깝게 만들어주는 3번째 용액을 찾아서 넣는다.
private static void addThirdSolution(int left, int right, int sum) {
int start = left + 1, end = right - 1;
while (start <= end) {
int mid = (start + end) >>> 1;
long sum3 = sum + solutions[mid]; // 3개의 용액 합 (3개 합이 10억 + 10억 + 10억일 수 있으므로 long타입으로)
long tmpSum = Math.abs(sum3); // 3개의 합의 절댓값
// 기존 0에 가까운 값보다 더 가깝다면 갱신
if (min > tmpSum) {
answer[0] = solutions[left];
answer[1] = solutions[mid];
answer[2] = solutions[right];
min = tmpSum;
}
// 3개의 합이 음수라면 0에 가깝게 하기 위해 큰 값 범위로 줄임
if (sum3 < 0) {
start = mid + 1;
// 3개의 합이 양수라면 0에 가깝게 하기 위해 작은 값 범위로 줄임
} else {
end = mid - 1;
}
}
}
}
🔅 문제풀이
import java.io.*;
import java.util.*;
public class Main {
static int[] solutions;
static int[] answer;
static long min;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringBuilder sb = new StringBuilder();
int n = Integer.parseInt(br.readLine());
solutions = new int[n];
StringTokenizer st = new StringTokenizer(br.readLine());
// 용액 특성값 초기화
for (int i = 0; i < n; i++) {
solutions[i] = Integer.parseInt(st.nextToken());
}
// 특성값을 오름차순 정렬
Arrays.sort(solutions);
answer = new int[3];
min = Long.MAX_VALUE;
// 1개를 미리 정하고 나머지에 대해서 투포인터 탐색
for (int i = 0; i < n - 2; i++) {
int left = i + 1, right = n - 1;
while (left < right) {
long sum = (long)solutions[i] + solutions[left] + solutions[right];
// 현재 합이 0에 가깝다면 갱신
if (min > Math.abs(sum)) {
answer[0] = solutions[i];
answer[1] = solutions[left];
answer[2] = solutions[right];
min = Math.abs(sum);
}
if (sum == 0) {
break;
}
if (sum < 0) left++;
else right--;
}
}
for (int val : answer) {
sb.append(val).append(" ");
}
System.out.println(sb.toString());
}
}
❗ 오답노트 / 필요한 지식
- 문제를 한가지 방법이 아닌 여러가지 방법으로 생각하자. 여러개일 경우 몇개는 고정하고 생각하는 방식을 떠올리자.