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)
문제의 조건을 만족하는 쌍의 개수를 출력한다.
💡 Point 💡
등장 여부 배열을 이용하자!
등장여부 배열이란 현재 읽고 있는 값을 기준으로 이전의 값들이 등장했는지 나타내는 배열이다. 예를 들어 {1,2,5} 라는 수열이 있을 때 현재 읽는 값이 2라면 등장여부 배열 occer에서 occer[1]은 1(true)이고, occer[5]는 0(false)이다.
이런 식으로 수열의 값을 하나씩 읽을 때마다 등장여부 배열을 업데이트한다. 그러면 새로운 값을 읽어 합이 x가 되는 값을 탐색할 때 O(1)의 시간복잡도를 가진다. 따라서 총 시간복잡도는 O(n)이다.
- 주어진 수열을 1개씩 읽는다.
- 현재 읽은 값이 x보다 크지 않고, 합이 x가 되는 값이 이전에 등장했었다면 cnt를 증가한다.
- 등장 배열에서 현재 읽은 값에 해당하는 인덱스의 값을 1로 바꾼다.
#include <iostream>
using namespace std;
int arr[1000001]; // 수열을 저장하는 배열
int occer[2000001]; // 등장 여부 배열
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
int n, x, cnt = 0;
cin >> n;
for (int i = 0; i < n; i++) cin >> arr[i];
cin >> x;
for (int i = 0; i < n; i++) {
if (x - arr[i] > 0 && occer[x - arr[i]]) cnt++;
occer[arr[i]] = 1;
}
cout << cnt;
return 0;
}