문제
N개의 수 중에서 어떤 수가 다른 수 두 개의 합으로 나타낼 수 있다면 그 수를 “좋다(GOOD)”고 한다.
N개의 수가 주어지면 그 중에서 좋은 수의 개수는 몇 개인지 출력하라.
수의 위치가 다르면 값이 같아도 다른 수이다.
입력
첫째 줄에는 수의 개수 N(1 ≤ N ≤ 2,000), 두 번째 줄에는 i번째 수를 나타내는 Ai가 N개 주어진다. (|Ai| ≤ 1,000,000,000, Ai는 정수)
출력
좋은 수의 개수를 첫 번째 줄에 출력한다.
예제 입력 1
10
1 2 3 4 5 6 7 8 9 10
예제 출력 1
8
이 문제를 들어온 num의 갯수만큼 돌면서 하나하나 비교하다보면 O(n) * O(n) * O(n)의 시간 복잡도가 걸린다.
총 2000개의 숫자가 나올 수 있으므로 2000^3은 8,000,000,000 즉 8초의 시간이 걸리게 된다.
이를 줄이기 위해 정렬시킨 후 binary Search를 사용하면 O(nlogn) + O(n) * O(n) * O(logn)이 나오게 되어 충분히 동작할 수 있다.
a + b = i를 다른 말로 하면 i - a = b 가 될 수 있다.
i에서 a를 뺀 후 b가 존재하는지 찾으면 a가 좋은 숫자인지 알 수 있다는 것이다.
b를 찾는것을 binary Search로 돌려보면 된다.
주의해야 할 점은 자기 자신인 i나 a를 두번 선택하는 것을 막기 위해 flag 배열을 만들어 사용하였다.
풀이 코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;
public class 좋다_1253 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
PrintWriter pw = new PrintWriter(System.out);
int n = Integer.parseInt(br.readLine());
int[] num = new int[n];
StringTokenizer st = new StringTokenizer(br.readLine());
for (int i = 0; i < n; i++) {
num[i] = Integer.parseInt(st.nextToken());
}
Arrays.sort(num);
int cnt = 0;
boolean[] visit = new boolean[n];
boolean[] flag = new boolean[n];
boolean[] flagA = new boolean[n];
for(int i = 0; i<num.length; i++){
flag[i] = true;
for(int a = 0; a<num.length; a++){
if(flag[a]) {
continue;
}
flagA[a] = true;
int b = num[i] - num[a];
int left = 0;
int right = num.length-1;
int mid = 0;
while(right >= left){
mid = (left + right)/2;
if(num[mid] > b) {
right = mid-1;
} else if(num[mid] < b) {
left = mid+1;
} else {
if(flagA[mid] || flag[mid]) {
int r = mid;
while((r>= 0 && r<=num.length-1)&& (num[mid] == num[r])) {
if((!flag[r] && !flagA[r])) {
visit[i] = true;
break;
}
r++;
}
break;
} else {
visit[i] = true;
break;
}
}
}
flagA[a] = false;
}
flag[i] = false;
}
for(int i = 0; i< visit.length; i++) {
if(visit[i]) {
cnt++;
}
}
pw.println(cnt);
br.close();
pw.close();
}
}
'알고리즘 > 백준' 카테고리의 다른 글
| [백준]숨바꼭질 1697 (1) | 2024.01.05 |
|---|---|
| [백준]촌수계산 2644 (1) | 2024.01.04 |
| [백준] 배열돌리기4 17406 (1) | 2023.12.07 |
| [백준]감시 15683 (2) | 2023.12.06 |
| [백준]보석 상자 2792 (1) | 2023.12.04 |