[백준 3273] 두 수의 합
백준 3273번 - 두 수의 합
❓ 문제
n개의 서로 다른 양의 정수 a1, a2, ..., an으로 이루어진 수열이 있다.
ai의 값은 1보다 크거나 같고, 1000000보다 작거나 같은 자연수이다.
자연수 x가 주어졌을 때, ai + aj = x (1 ≤ i < j ≤ n)을 만족하는 (ai, aj)쌍의 수를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 수열의 크기 n이 주어진다.
다음 줄에는 수열에 포함되는 수가 주어진다.
셋째 줄에는 x가 주어진다. (1 ≤ n ≤ 100000, 1 ≤ x ≤ 2000000)
예제 입력 1
9
5 12 7 10 9 1 2 3 11
13
예제 출력 1
3
✏️ 풀이
for 문을 2개 중첩해서 brute-force로 모든 경우의 수를 조사해버리면, TLE(Time Limit Exceeded)가 난다.
우리는 조사해야 할 범위가 100,000이기 때문에 for문 중첩 없이 해결해야한다.
그렇다면 어떻게 해결할까?
Two Pointer
알고리즘을 이용한다.
Two Pointer
알고리즘은 두 개의 포인터를 이용하여 1차원 배열에서 원하는 결과를 얻을 수 있는 알고리즘이다.
- 배열을 sort함(오름차순)
- 각각의 포인터는 배열의 처음과 끝을 가리킴
- sum = arr[처음 포인터] + arr[끝 포인터]
- 만약 sum과 찾는 값이 같다면 끝 포인터-=1 하고 count 증가
- sum이 찾는 값보다 작다면 처음 포인터+=1
- sum이 찾는 값보다 크면 끝포인터-=1
- 처음 포인터와 끝 포인터가 같아지면(만나면) break
- 반복
위 조건으로 for문 2중첩 O(N^2)의 시간복잡도를 O(N)으로 줄일 수 있다.
Two Pointer
는 자주 쓰이는 기법이니 문제를 풀며 감을 익히도록 하자.
✔️ 정답 코드
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
vector<int> number;
int result = 0;
int main(void) {
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n, x, temp;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> temp;
number.push_back(temp);
}
cin >> x;
int l = 0, r = number.size() - 1;
sort(number.begin(), number.end());
while (1) {
if (l == r)
break;
int sum = number[l] + number[r];
if (sum == x) {
result++;
r--;
}
else if (sum > x)
r--;
else
l++;
}
cout << result;
return 0;
}
Leave a comment