백준 - 두 수의 합 (3273)

아놀드·2021년 10월 2일
0

백준

목록 보기
35/73
post-thumbnail

1. 문제

문제 링크

문제

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)

출력

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

2. 풀이

주먹구구식

단순히 O(N^2) 풀이를 하면 시간 초과가 납니다.

int a[100000];

int main(void) {
	ios::sync_with_stdio(0);
	cin.tie(0);

	int n, x;

	cin >> n;

	for (int i = 0; i < n; i++) {
		cin >> a[i];
	}

	cin >> x;

	int ans = 0;

	for (int i = 0; i < n; i++) {
		for (int j = i + 1; j < n; j++) {
			if (a[i] + a[j] == x) ans++;
		}
	}

	cout << ans;
	return 0;
}

하지만 잘 생각해보면 탐색 범위를 많이 줄일 수 있습니다.
a 배열을 정렬한 후에
i는 배열의 왼쪽 부분, j는 배열의 오른쪽 부분을 가리키게 하는
투포인터 방법으로 이 문제를 O(NlogN)에 해결할 수 있습니다.

  • a[i] + a[j] == x일 때, i 다음에 있는 수도 만족하는지 확인하기 위해
    i를 증가시킵니다. -> i++
  • a[i] + a[j] < x일 때, 현재 i번째 수가 작아서 x를 만들기 적합하지 않다는 뜻이므로,
    i를 증가시킵니다. -> i++
  • a[i] + a[j] > x일 때, 현재 j번째 수가 커서 x를 만들기 적합하지 않다는 뜻이므로,
    j를 감소시킵니다. -> j--
  • 1 ≤ i < j ≤ n를 만족해야 하므로 i < j일 때만 위의 과정을 반복합니다.

간단하죠?

3. 전체 코드

#include <iostream>
#include <algorithm>

using namespace std;

int a[100000];

int main(void) {
	ios::sync_with_stdio(0);
	cin.tie(0);

	int n, x;

	cin >> n;

	for (int i = 0; i < n; i++) {
		cin >> a[i];
	}

	cin >> x;

	sort(a, a + n);

	int ans = 0, i = 0, j = n - 1;

	while (i < j) {
		if (a[i] + a[j] == x) {
			i++;
			ans++;
		}
		else if (a[i] + a[j] < x) {
			i++;
		}
		else {
			j--;
		}
	}

	cout << ans;
	return 0;
}
profile
함수형 프로그래밍, 자바스크립트에 관심이 많습니다.

0개의 댓글