개발 공부~

[백준 - 1300] K번째 수 .java 본문

코딩테스트/백준

[백준 - 1300] K번째 수 .java

머밍 2024. 7. 31. 16:07

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

(이 문제는 도움을 받았다)

 

<문제 분석>

k의 범위가 n의 2승인데 n이 10의 5승보다 작거나 같기 때문에 시간 복잡도가 n^2인 알고리즘을 사용할 수 없다.

-> 이진 탐색 사용 

-> 중앙값보다 작은 수의 개수를 세면서 범위를 절반씩 줄이는 방법으로 b[k]를 구한다.

 

푸는 결정적인 아이디어를 도움받았다.

(참고 책/  do it! 알고리즘 코딩테스트 - 자바편)

 

  • 2차원 배열: n행이 n의 배수로 구성
  • 2차원 배열의 k번째 수는 k를 넘지 않는다. -> k보다 작은 수의 개수를 세는것이 포인트
  • 애초에 이진탐색을 생각하는게 어려운 문제였다.
  • start = 시작
  • end = 찾는 값 = k
  • 각 행에서 mid보다 작거나 같은 수의 개수: mid / 각행의 첫번째 값
  • math.min(mid/i, n) : mid보다 작거나 같은 수의 개수 
  • mid보다 작은 수의 개수 < k: start = mid +1
  • mid보다 작은 수의 개수 >= k : end = mid -1, 정답을 mid로 업데이트 
  • start가 end보다 커지면 종료 -> 정답 출력

 

괜히 골드 1이 아니다.. 코드만 보면 간단하지만 이 문제에서 이진탐색을 떠올리고 mid값이 몇번째 값인지 k보다 작은 수를 세는 계산식을 세우는것이 어려웠다.. 처음엔 힌트를 봐도 몰랐다..

import java.util.*;

public class Main {
    public static void main(String[] args)  {
        Scanner sc = new Scanner(System.in);
        // 입력 받아 저장
        int n = sc.nextInt();
        int k = sc.nextInt();

        long start = 1;
        long end = k;
        long answer = 0;

        //이진탐색
        while (start <= end) {
            long mid = (start + end) / 2;
            long count = 0;

            //중앙값보다 작거나 같은 수의 개수 구하기
            for(int i = 1; i <= n; i++) {
                count += Math.min(mid/i, n);
            }
            if(count < k) {
                start = mid + 1;
            } else{
                end = mid - 1;
            }
            
        }
        System.out.println(start);


    }

}

'코딩테스트 > 백준' 카테고리의 다른 글

[백준 - 1744] 수 묶기 .java  (0) 2024.08.01
[백준 - 1715] 카드 정렬하기  (0) 2024.07.31
[백준 - 2343] 기타 레슨 .java  (0) 2024.07.31
[백준 - 11047] 동전 0 .java  (0) 2024.07.31
[백준 - 1920] 수 찾기 .java  (0) 2024.07.31