Q 3273 두 수의 합
💡 문제 요약 및 분석
a[n] 배열에서 a[i] + a[j] = x 가 되는 경우의 수를 모두 찾아라.
💡 알고리즘 설계
✅ n의 범위가 최대 100,000이기 때문에 이중for문을 쓰면 타임아웃이 된다. map 을 활용하자.
입력
- 표준입력으로 배열 int[N] a 생성
연산
- for문으로 배열 a 반복
- a[i] - x 를 key 로 갖는 값이 있는지 확인하고 있으면 count++
- a[i] 를 key로 추가한다.
출력
- count 변수를 출력한다.
💡 코드
import java.util.*;
public class Main {
static int read() throws Exception {
int n = 0, c = 0;
while ((c = System.in.read()) > 47) n = (n << 3) + (n << 1) + (c & 15);
return n;
}
public static void main(String[] args) throws Exception {
int n = read();
int[] A = new int[n];
for (int i = 0; i < n; i++) {
A[i] = read();
}
int x = read();
int count = 0;
Map<Integer, Integer> memo = new HashMap<>();
for (int i = 0; i < n; i++) {
count += memo.getOrDefault(x - A[i], 0);
memo.put(A[i], 1);
}
System.out.println(count);
}
}
💡 시간 복잡도, 공간 복잡도
시간 복잡도 | 공간 복잡도 |
---|---|
O(n) | O(n) |
💡 다른 풀이
아예 공간을 더 써서 시간을 절약하는 풀이법도 있었다. n개만큼의 배열 arr을 만들어서 arr[read()] 로 입력되는 값에 true 표시하여 모든 위치를 방문하는 로직도 있었다. 이 경우 중복을 방지하기 위해 x / 2 + 1 부터 검사를 시작한 것이 인상적이었다. 내가 사용한 HashMap도 평균 조회 시간이 O(1) 로 상수 시간만큼 걸리지만, 배열의 경우 상수가 훨씬 작다고 한다.
class Main {
static int read() throws Exception {
int c, n = System.in.read() & 15;
while ((c = System.in.read()) > 47) n = (n << 3) + (n << 1) + (c & 15);
return n;
}
public static void main(String[] args) throws Exception {
int n = read();
boolean[] arr = new boolean[1000001];
for (int i = 0; i < n; i++) {
arr[read()] = true;
}
int x = read();
int answer = 0;
for (int i = x / 2 + 1; i < 1000001; i++) {
int remain = x - i;
if (remain <= 0) break;
if (arr[i] && arr[remain]) answer++;
}
System.out.println(answer);
}
}