PS/이코테
[이코테][Java] 정렬된 배열에서 특정 수의 개수 구하기
nyrimmm
2025. 2. 11. 17:22
문제 설명
N개의 원소를 포함하고 있는 수열이 오름차순으로 정렬되어 있을 때, 이 수열에서 x가 등장하는 횟수를 계산하세요.
예를 들어 수열 {1, 1, 2, 2, 2, 2, 3}이 있을 때 x=2라면, 4를 출력
시간복잡도 O(log N)으로 알고리즘을 설계하지 않으면 '시간초과 판정'
입력조건
- 첫째 줄에 N과 x
- 둘째 줄에 n개의 원소
출력조건
- 수열에서 값이 x인 원소의 개수
- 값이 x인 원소가 없다면 -1
입출력 예시
입력예시 | 출력예시 |
7 2 1 1 2 2 2 2 3 |
4 |
7 4 1 1 2 2 2 2 3 |
-1 |
문제 풀이
- 시간복잡도 O(log N) 로 설계해야하기 때문에 순차 탐색으로는 풀 수 없다. → 이진탐색으로 풀이
- x가 처음으로 등장하는 위치와 마지막 위치를 찾아서 빼주면 x의 개수를 구할 수 있다.
- firstIndex() : x가 처음으로 등장하는 위치를 찾는 이진 탐색 함수
- lastIndex() : x의 마지막 위치를 찾는 이진 탐색 함수
import java.io.*;
import java.util.StringTokenizer;
public class Main {
public static int x, count = 0;
public static int[] array;
//x가 처음 위치를 찾는 이진 탐색
public static int firstIndex(int start, int end) {
while(start < end){
int mid = (start + end) / 2;
if(array[mid] >= x){
end = mid;
} else {
start = mid + 1;
}
}
return end;
}
//x의 마지막 위치를 찾는 이진 탐색
public static int lastIndex(int start, int end) {
while(start < end){
int mid = (start + end) / 2;
if(array[mid] > x){
end = mid;
} else {
start = mid + 1;
}
}
return end;
}
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());
x = Integer.parseInt(st.nextToken());
array = new int[n];
st = new StringTokenizer(br.readLine());
for (int i = 0; i < n; i++) {
array[i] = Integer.parseInt(st.nextToken());
}
int first = firstIndex(0, n);
int last = lastIndex(0, n);
System.out.println((last - first == 0) ? -1 : last - first);
}
}
처음에는 아래와 같이 재귀 함수를 사용해서 이진 탐색을 구현했다.
- array[mid] == x이면 mid를 중심으로 왼쪽, 오른쪽 영역에 x가 있는지 재귀함수를 호출해서 탐색한다.
- 하지만 이방법은 시간복잡도가 O(log N)을 만족하지 못하는 것 같다...
public static int binary_search(int start, int end) {
if (start > end) {
return -1;
}
int mid = (start + end) / 2;
if (array[mid] == x) { //x와 같다면
count++;
binary_search(mid + 1, end); //mid를 중심으로 오른쪽 영역에 x가 있는지 확인
binary_search(start, mid - 1); //mid를 중심으로 왼쪽 영역에 x가 있는지 확인
} else if (array[mid] < x) {
binary_search(mid + 1, end);
} else {
binary_search(start, mid - 1);
}
return count;
}
[참고서적]
이것이 취업을 위한 코딩 테스트다 with 파이썬 by 나동빈