숫자를 key, 등장 횟수를 value로 저장해서 O(1)로 조회했다.
주의: 반복문 안에서 System.out.println()을 매번 호출하면 I/O 비용이
M번(최대 50만번) 누적되어 시간초과가 발생한다.
→ StringBuilder로 모아서 한 번에 출력해야 한다.
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken());
Map<Integer, Integer> map = new HashMap<>();
st = new StringTokenizer(br.readLine());
for (int i = 0; i < n; i++) {
int num = Integer.parseInt(st.nextToken());
map.put(num, map.getOrDefault(num, 0) + 1);
}
st = new StringTokenizer(br.readLine());
int m = Integer.parseInt(st.nextToken());
st = new StringTokenizer(br.readLine());
StringBuilder sb = new StringBuilder();
for (int i = 0; i < m; i++) {
int target = Integer.parseInt(st.nextToken());
sb.append(map.getOrDefault(target, 0)).append(" ");
}
System.out.println(sb);
}
}
정렬 후 lowerBound(첫 등장 인덱스) 와 upperBound(마지막 등장 다음 인덱스) 의
차이로 개수를 구했다.
upper - lower = 해당 숫자의 개수
핵심 주의사항
rt = numbers.length (length-1 아님!)while(lt < rt) (<= 아님!)import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken());
int[] numbers = new int[n];
st = new StringTokenizer(br.readLine());
for (int i = 0; i < n; i++) {
numbers[i] = Integer.parseInt(st.nextToken());
}
Arrays.sort(numbers);
st = new StringTokenizer(br.readLine());
int m = Integer.parseInt(st.nextToken());
st = new StringTokenizer(br.readLine());
StringBuilder sb = new StringBuilder();
for (int i = 0; i < m; i++) {
int target = Integer.parseInt(st.nextToken());
int count = upper(numbers, target) - lower(numbers, target);
sb.append(count).append(" ");
}
System.out.println(sb);
}
public static int lower(int[] numbers, int target) {
int lt = 0, rt = numbers.length;
while (lt < rt) {
int mid = (lt + rt) / 2;
if (numbers[mid] < target) lt = mid + 1;
else rt = mid;
}
return lt;
}
public static int upper(int[] numbers, int target) {
int lt = 0, rt = numbers.length;
while (lt < rt) {
int mid = (lt + rt) / 2;
if (numbers[mid] <= target) lt = mid + 1;
else rt = mid;
}
return lt;
}
}
System.out.println()을 반복문 안에서 호출해서 시간초과가 발생했다.StringBuilder로 모아서 한 번에 출력하는 습관을 기르자.rt = length와 while(lt < rt) 조건이 헷갈렸다.rt를 배열 길이로 설정하고 lt < rt로 순회하는 것이 정석이다.