[백준 2470][💛5] 두 용액 (투포인터 알고리즘)
카테고리: BOJ
태그: Coding Test Cpp Algorithm
🚀 난이도
💛 골드 5
🚀 문제
예제 입력 1
5
-2 4 -99 -1 98
예제 출력 1
-99 98
🚀 내 풀이 ⭕
#include <iostream>
#include <vector>
#include <algorithm>
#define INF 2000000000
using namespace std;
vector<int> answer(2);
int main() {
int N;
cin >> N;
vector<int> arr(N);
for (int i = 0; i < N; ++i)
cin >> arr[i];
sort(arr.begin(), arr.end()); // 정렬 필수!
int start = 0; // start 은 왼쪽 끝에서
int end = N - 1; // end 은 오른쪽 끝에서 시작
int min = INF; // 현재까지 0 에 가장 가까웠던 합
while (start < end) {
int sum = arr[start] + arr[end];
if (min > abs(sum)) {
min = abs(sum);
answer[0] = arr[start];
answer[1] = arr[end];
if (sum == 0)
break;
}
if (sum < 0)
start++;
else
end--;
}
cout << answer[0] << " " << answer[1];
}
양쪽 끝에서 출발한 두 포인터가 서로 반대 방향으로 다가와서 좁혀지는 형태의 투포인터 알고리즘이다. start -> <- end 요렇게!
start
-> 방향end
<- 방향
서로의 합이 가장 0 에 가까운 두 수를 구해야하기 때문에 먼저 오름차순 정렬을 한 후, 양쪽 끝에서부터 두 포인터를 이용하여 0 에 가까운 두 수를 구해나간다.
min
은 현재까지 구한 두 수의 합 중 가장 0 에 가까웠던 합. (가장 “가까웠던” 이니까 절대값으로 넣어야 한다.)
- 1️⃣ 먼저 오름차순 정렬을 한다. (음수거나 작을 수록 왼쪽, 양수거나 클 수록 오른쪽에 위치하도록)
- 2️⃣ 양쪽 끝의 두 포인터가 가리키는 원소끼리 더하여 최대한 두 수의 합이 0 에 가깝도록 두 포인터를 업데이트 해나간다.
- arr[start] + arr[end] < 0
- 0 보다 작으므로 두 수의 합이 더 커져야 0 에 가까워질 것이다. 그러므로 더 커져야하기 떄문에
start
를 증가시킨다. (작은 값을 더 큰 값으로 대체)
- 0 보다 작으므로 두 수의 합이 더 커져야 0 에 가까워질 것이다. 그러므로 더 커져야하기 떄문에
- arr[start] + arr[end] > 0
- 0 보다 크므로 두 수의 합이 더 작아야 0 에 가까워질 것이다. 그러므로 더 작아져야하기 떄문에
end
를 감소시킨다. (큰 값을 더 작은 값으로 대체)
- 0 보다 크므로 두 수의 합이 더 작아야 0 에 가까워질 것이다. 그러므로 더 작아져야하기 떄문에
- arr[start] + arr[end] < 0
- 3️⃣
min
업데이트 하기- arr[start] + arr[end] < min
- 기존에 구했던 두 수의 합보다 더 작은 합이 나왔으니 정답 후보가 될 수 있다.
min
과answer
를 업뎃한다. - 혹시 이미 0 이 나왔으면 더 찾을 필요 없으므로 종료.
- 기존에 구했던 두 수의 합보다 더 작은 합이 나왔으니 정답 후보가 될 수 있다.
- arr[start] + arr[end] < min
4 -99 -1 7 -2
- 우선 정렬하기 👉 -99 -2 -1 4 7
- -99 -2 -1 4 7 : -99 + 7 < 0 이므로 더 커져야 함 (92)
- -99 -2 -1 4 7 : -2 + 7 > 0 이므로 더 작아져야 함 (5)
- -99 -2 -1 4 7 : -2 + 4 > 0 이므로 더 작아져야 함 (2)
- -99 -2 -1 4 7 : -2 + -1 < 0 이므로 더 커져야 함 (3)
- start >= end 이므로 종료
답은 가장 0 에 가까웠던 (2) -2 4 가 된다.
🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄
댓글 남기기