10816번

2023. 2. 16. 13:17·CS 이론/알고리즘
728x90

https://www.acmicpc.net/problem/10816

 

10816번: 숫자 카드 2

첫째 줄에 상근이가 가지고 있는 숫자 카드의 개수 N(1 ≤ N ≤ 500,000)이 주어진다. 둘째 줄에는 숫자 카드에 적혀있는 정수가 주어진다. 숫자 카드에 적혀있는 수는 -10,000,000보다 크거나 같고, 10,

www.acmicpc.net

이 문제는 이분탐색 문제인데 lowerbound와 upperbound의 개념을 알아야 풀 수 있는 문제였다.. 그래서 애를 많이 먹었다.

나는 lowerbound와 upperbound를 말로는 이해하지 못했다.. 그림으로 이해했다.

 

먼저, lowerbound는 배열에서 범위 내의 원소들 중 찾으려는 값(key)보다 크거나 같은(key<=)첫번째 원소의 인덱스를 반환하는 것이다.

만약 원소가 없다면 end값을 리턴한다.

 

upperbound는 배열에서 처음으로 찾으려는 값(key)을 초과하는(key<) 원소의 인덱스를 반환한다. 만약 그런 원소가 없다면 end값을 리턴한다.

 

말로 하면 조금 헷갈리고 이해가 잘 안된다.

그래서 표를 그려봤다.

index 0 1 2(lower) 3 4 5(upper)
arr 0 3 5 5 5 6

위의 표에서 찾으려는 key값이 5일때, lowerbound는 2이고, upperbound는 5이다.

즉, lowerbound는 찾으려는 값중에서 제일 앞에 있는 값이고, upperbound는 중복되는 찾으려는 값들의 바로 다음 값이다.

 

그래서 이분탐색을 진행하면

먼저 lowerbound를 찾는 이분 탐색은 아래와 같다.

public static int lowerBound(int find, int start, int end){
    int mid;
    while (end-start>0){
        mid = (start+end)/2;
        if(arrN[mid]<find){
            start=mid+1;//찾으려는 값이 중간값보다 크면 시작지점을 옮긴다. 고려할 점은 시작지점은 찾으려는 값과 같아야한다. 
            //그래서 찾으려는 값이 크니까 +1을 해주는 것이다.
        }else end=mid;//찾으려는 값이 중간값보다 작거나 같으면(find<=arr[mid]) 끝지점을 중간값으로한다.
    }
    return end;
}

그 다음 upperbound는 아래와 같다.

public static int upperBound(int find, int start, int end){
    int mid;
    while (end-start>0){
        mid = (start+end)/2;

        if(arrN[mid]<=find){
            start=mid+1;//찾으려는 값보다 작거나 같으면 시작점을 옮긴다. 
        }else end=mid;//찾으려는 값보다 크면 끝점을 옮긴다. - 옮겨진 끝점이 찾으려는 값의 다음으로 큰 값이다.
    }
    return end;
}

그래서 이렇게 구한 두 범위의 값을 upperbound에서 lowerbound를 빼면 찾으려는 값의 갯수를 구할 수 있다.

 

정답 코드는 아래와 같다.

package backjoon;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class b10816 {
    static int M;
    static int[] countArr;
    static int[] arrN;
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        int N = Integer.parseInt(br.readLine());
        StringTokenizer st = new StringTokenizer(br.readLine());
        arrN = new int[N];
        for(int i=0; i<N; i++){
            arrN[i]= Integer.parseInt(st.nextToken());
        }

        Arrays.sort(arrN);

        M = Integer.parseInt(br.readLine());
        st = new StringTokenizer(br.readLine());
        int[] arrM = new int[M];
        countArr = new int[M];
        for(int i=0; i<M; i++){
            arrM[i]= Integer.parseInt(st.nextToken());
        }

        for(int i=0; i<M; i++){
            int count = upperBound(arrM[i],0,N) - lowerBound(arrM[i],0,N);
            countArr[i]=count;
        }

        StringBuilder sb = new StringBuilder();
        for (int i : countArr) {
            sb.append(i).append(" ");
        }
        System.out.println(sb);
    }

    public static int lowerBound(int find, int start, int end){
        int mid;
        while (end-start>0){
            mid = (start+end)/2;
            if(arrN[mid]<find){
                start=mid+1;
            }else end=mid;
        }
        return end;
    }
    public static int upperBound(int find, int start, int end){
        int mid;
        while (end-start>0){
            mid = (start+end)/2;

            if(arrN[mid]<=find){
                start=mid+1;
            }else end=mid;
        }
        return end;
    }
}

 

728x90

'CS 이론 > 알고리즘' 카테고리의 다른 글

10451번  (1) 2023.02.20
4963번  (0) 2023.02.18
1021번  (1) 2023.02.15
5639번  (0) 2023.02.14
1991번  (0) 2023.02.13
'CS 이론/알고리즘' 카테고리의 다른 글
  • 10451번
  • 4963번
  • 1021번
  • 5639번
Bello's
Bello's
개발하는 벨로
  • Bello's
    벨로의 개발일지
    Bello's
  • 전체
    오늘
    어제
    • 분류 전체보기 (199) N
      • 노예 일지 (7)
        • 스타트업 노예일지 (3)
      • CS 이론 (81)
        • 학과 수업 (4)
        • 알고리즘 (64)
        • 시스템 프로그래밍 (3)
        • 데이터 통신 (1)
        • 운영체제 (2)
        • 데이터베이스 (1)
      • project (3)
      • 나는 감자다. (4)
      • Spring (27)
      • 모각코 (45)
        • 절개와지조(모각코) (7)
        • 어쩌다보니 박준태가 조장이조 (11)
        • 어쩌다보니 박준태가 또 조장이조 (12)
      • LikeLion🦁 (20)
      • 캘리포니아 감자 (4)
      • OpenSource Contribute (1)
      • 우아한테크벨로 (1) N
        • 프리코스 회고록 (6)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    JPA
    나는 감자
    감자
    Spring
    백준
    자바
    회고록
    절개와지조
    누적합
    오블완
    BFS
    타임리프
    프리코스
    어렵다
    모각코
    그래프 순회
    뛰슈
    DFS
    8기
    티스토리챌린지
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
Bello's
10816번
상단으로

티스토리툴바