본문 바로가기

ps(알고리즘)

k번째 수

1 2 3
2 4 6 
3 6 9

1 2 2 3 3 4 6 6

 

N이 3일 때는 이렇게 B 배열이 작성된다.

B의 k번째 수를 구해야 한다.

즉, A에 있는 N제곱개의 숫자 중에서 k번째로 작은 수를 구하는 문제이다.

그냥 N제곱 크기의 배열을 만들어서 정렬을 해버리면 N^2 * 2logN의 시간이 걸려서 애매하다.

시간이 되더라도 어차피 N^2 크기의 배열을 만들 메모리가 없기 때문에 안된다.

 

다른 방법을 찾아야 한다.

어떤 숫자를 정하고 그 숫자가 몇번째로 작은 수인지 구하는 과정은 N의 시간만에 할 수 있다.

그럼 그 숫자가 x번째로 작은 수라고 가정하고 x가 k보다 작으면 숫자를 키우고, k보다 크면 숫자를 줄이면 된다.

즉, 이분탐색으로 해결할 수 있다.

long long bin_search(long long s, long long e)
{
    if(s==e) return s;
    long long m = (s+e)/2;
    long long cnt = 0;
    for(int i=1;i<=N;i++)
    {
        cnt += min(N,m/i);
    }
    if(cnt<k)
    {
        return bin_search(m+1,e);
    }
    else
    {
        return bin_search(s,m);
    }
}

숫자를 m으로 정하고 m 보다 작거나 같은 수의 개수를 cnt에 담았다.

for문 안에서 A배열을 한줄씩 돌면서 최대 N개, m/i로 개수를 구해서 더해줬다.

그리고 cnt와 k를 비교해 범위를 이분탐색으로 좁혀가며 k번째 수를 구했다.

#include<stdio.h>
#include<algorithm>
using namespace std;
long long N,k;
long long bin_search(long long s, long long e)
{
    if(s==e) return s;
    long long m = (s+e)/2;
    long long cnt = 0;
    for(int i=1;i<=N;i++)
    {
        cnt += min(N,m/i);
    }
    if(cnt<k)
    {
        return bin_search(m+1,e);
    }
    else
    {
        return bin_search(s,m);
    }
}
int main()
{
    scanf("%lld %lld",&N,&k);
    printf("%lld",bin_search(1,k));
}

전체 코드이다.

'ps(알고리즘)' 카테고리의 다른 글

외판원 순회  (0) 2024.11.04
최솟값과 최댓값  (0) 2024.10.30
구슬 탈출 2  (0) 2024.10.28
구간 합 구하기  (0) 2024.10.28
공항  (0) 2024.09.03