1. 문제 이해
N개의 수 중에서 다른 수 2개의 합으로 나타낼 수 있는 수의 개수를 세야 한다.
즉, A = B + C 를 만족하는 A의 개수를 구한다. ( 단, A != B && B != C && B != C )
2. 문제 풀이
주어진 N의 범위는 (1 ≤ N ≤ 2,000)
주어지는 수의 범위는 절댓값 10억 이하이므로, INT32 범위를 벗어나지 않는다.
A = B + C 인 A를 구하기 위해, 서로 다른 B와 C를 구해야 한다. B와 C는 투포인터로 구할 수 있다. 이 때, 선행으로 정렬을 해야 한다. 그래야, Left, Right 어느 쪽을 줄이고 늘릴지 판단할 수 있다.
A = B + C 일 때 B를 Left 인덱스의 수, C를 Right 인덱스의 수로 정하면 A가 표현가능한 지 구할 수 있다.
시간복잡도는 N^2 이므로 시간초과가 걸리지 않는다.
배열 자료구조에서 Left와 Right 인덱스를 가장 왼쪽과 가장 오른쪽으로 초기화 한다.
10
1 2 3 4 5 6 7 8 9 10
입력값이 위와 같은 경우, Left = 0, Right = 9 이다.
만약 '6'이란 수가 서로 다른 두개의 합으로 나타낼 수 있는지 구하기 위해 Left 와 Right를 바꿔가면서 찾는다.
초기 Left, Right 값에 의하면 num[0] + num[9] 이므로 둘의 합은 11이다. 11은 6보다 크므로 RIght를 줄여 합을 줄인다.
만약 합이 Key값, 즉 6보다 작다면 Left를 늘려 합을 늘릴 수 있다.
이 때, Left와 Right는 같아 질 수 없고 Left와 Right의 값은 6의 인덱스가 될 수 없다.
예를 들어 입력값이
5
0 1 2 1 1
이고 , 구하고자 하는 A가 2이라면 2 = 0 + 2 가 되어서는 안된다.
혹은 이분탐색으로 풀 수 있다.
A = B + C 일 때, A - B = C라고 하자.
A와 B를 2차원 배열로 표현하고, C를 이분탐색으로 찾는다. A와 B는 N^2 만큼 시간이 걸리고, 이분탐색 시간은 LogN이다. 그러므로 시간복잡도는 N^2 LogN 이므로 시간초과가 걸리지 않는다.
그러나, A,B,C는 모두 다른 수이므로 예외처리를 해줘야 한다!
3. 제출 결과
4. 문제 코드
#include <iostream>
#include <algorithm>
using namespace std;
int num[2002];
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int n; cin >> n;
for(int i=0; i<n; i++) {
cin >> num[i];
}
sort(num, num+n);
int cnt = 0;
for(int i=0; i<n; i++) {
int left = 0, right = n-1;
int key = num[i];
while(left < right) {
if(left == i) { left++;}
else if (right == i) { right--;}
else if (key > num[left] + num[right]){left++;}
else if (key == num[left] + num[right]) {
cnt++; break;
} else { right --;}
}
}
cout << cnt;
}
'Algorithm Problem > 백준' 카테고리의 다른 글
[백준] 10942 - 팰린드롬? (0) | 2022.06.23 |
---|---|
[백준] 6198번 - 옥상 정원 꾸미기 (0) | 2022.06.21 |
[백준] 5582번 - 공통 부분 문자열 (0) | 2022.04.02 |
[백준] 1600번 - 말이 되고픈 원숭이 (0) | 2022.03.30 |
[백준] 12685번 - 평범한 배낭 (0) | 2022.02.07 |