[백준/C++] 3273번 두 수의 합

dev.hyeon·2023년 1월 6일
0

알고리즘

목록 보기
39/44
post-thumbnail

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)

출력

문제의 조건을 만족하는 쌍의 개수를 출력한다.


풀이

시간복잡도 O(n)

💡 Point 💡
등장 여부 배열을 이용하자!

등장여부 배열이란 현재 읽고 있는 값을 기준으로 이전의 값들이 등장했는지 나타내는 배열이다. 예를 들어 {1,2,5} 라는 수열이 있을 때 현재 읽는 값이 2라면 등장여부 배열 occer에서 occer[1]은 1(true)이고, occer[5]는 0(false)이다.

이런 식으로 수열의 값을 하나씩 읽을 때마다 등장여부 배열을 업데이트한다. 그러면 새로운 값을 읽어 합이 x가 되는 값을 탐색할 때 O(1)의 시간복잡도를 가진다. 따라서 총 시간복잡도는 O(n)이다.

  1. 주어진 수열을 1개씩 읽는다.
  2. 현재 읽은 값이 x보다 크지 않고, 합이 x가 되는 값이 이전에 등장했었다면 cnt를 증가한다.
  3. 등장 배열에서 현재 읽은 값에 해당하는 인덱스의 값을 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;
}

0개의 댓글