숫자 카드 문제와 유사하지만 숫자 카드 2 문제는 숫자카드가 중복되어 있어서 카드 갯수를 다 구해야 한다는 차이점이 있다.
이 문제도 숫자 카드 문제와 똑같이 이진 탐색으로 Mid값을 구해주고 앞 뒤로 중복된 카드가 있는지 구해주면 되는 줄 알고 코드를 작성했다.
<시간초과>
import java.io.*;
import java.util.Arrays;
import java.util.StringTokenizer;
public class Main {
static int N;
static int M;
static int[] arr;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
N = Integer.parseInt(br.readLine());
arr = new int[N];
StringTokenizer st = new StringTokenizer(br.readLine());
for(int i = 0; i<N; i++){
arr[i]=Integer.parseInt(st.nextToken());
}
Arrays.sort(arr);
M=Integer.parseInt(br.readLine());
st = new StringTokenizer(br.readLine());
for(int i=0; i<M; i++){
int num = Integer.parseInt(st.nextToken());
bw.write(BinarySearch(num)+" ");
}
bw.flush();
}
public static int BinarySearch(int num) {
int Tail = 0;
int Head = N - 1;
int count=0;
while (Head >= Tail) {
int Mid = (Head + Tail) / 2;
int MidValue = arr[Mid];
if (MidValue > num) {
Head = Mid - 1;
} else if (MidValue < num) {
Tail = Mid + 1;
} else {
int temp=Mid;
count++;
while (Mid<N-1) {
if(arr[Mid+1]==num){
count++;
Mid++;
}
else{
break;
}
}
Mid=temp;
while(Mid>0){
if(arr[Mid-1]==num){
count++;
Mid--;
}
else{
break;
}
}
break;
}
}
return count;
}
}
이 코드의 치명적인 문제는 찾고자 하는 숫자를 찾았는데 그 앞으로 500,000개의 숫자가 다 똑같은 숫자라면 무조건 시간초과가 뜰 수 밖에 없다.
이 방법 외에는 달리 방법이 떠오르지 않아서 구글링을 한 결과 조금 다른 이진탐색을 수행해야 한다는 것을 알게 되었다.
public static int findStart(int num){
int Head = arr.length;
int Tail=0;
while(Head>Tail){
int Mid = (Head+Tail)/2;
if(num<=arr[Mid]){
Head=Mid;
}
else{
Tail=Mid+1;
}
}
return Tail;
}
public static int findLast(int num){
int Head = arr.length;
int Tail = 0;
while(Head>Tail){
int Mid = (Head+Tail)/2;
if(num<arr[Mid]){
Head=Mid;
}
else{
Tail=Mid+1;
}
}
return Tail;
}
findStart ==> 찾고자 하는 숫자가 시작되는 곳의 인덱스를 찾는다.
findLast ==> 찾고자 하는 숫자가 끝나는 곳의 다음 인덱스를 구한다.
findLast-findStart == 찾고자 하는 값의 갯수
<전체 코드>
import java.io.*;
import java.util.Arrays;
import java.util.StringTokenizer;
public class Problem10816 {
static int N;
static int M;
static int[] arr;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
N = Integer.parseInt(br.readLine());
arr = new int[N];
StringTokenizer st = new StringTokenizer(br.readLine());
for(int i = 0; i<N; i++){
arr[i]=Integer.parseInt(st.nextToken());
}
Arrays.sort(arr);
M=Integer.parseInt(br.readLine());
st = new StringTokenizer(br.readLine());
for(int i=0; i<M; i++){
int num = Integer.parseInt(st.nextToken());
bw.write(findLast(num)-findStart(num)+" ");
}
bw.flush();
}
public static int findStart(int num){
int Head = arr.length;
int Tail=0;
while(Head>Tail){
int Mid = (Head+Tail)/2;
if(num<=arr[Mid]){
Head=Mid;
}
else{
Tail=Mid+1;
}
}
return Tail;
}
public static int findLast(int num){
int Head = arr.length;
int Tail = 0;
while(Head>Tail){
int Mid = (Head+Tail)/2;
if(num<arr[Mid]){
Head=Mid;
}
else{
Tail=Mid+1;
}
}
return Tail;
}
}
'알고리즘 > 백준' 카테고리의 다른 글
백준-1780번/종이의 개수(java) (0) | 2024.12.29 |
---|---|
백준-11728번/배열 합치기 (java) (2) | 2024.10.07 |
백준-1541번/잃어버린 괄호 (java) (2) | 2024.10.05 |
백준-10610번/30 (java) (1) | 2024.10.04 |
백준-2875번/대회 or 인턴 (java) (0) | 2024.10.03 |