input | output |
3 7 |
6 |
해당 문제는 단순히 이중 배열을 선언하여 정렬하려고 한다면 시간 초과가 발생할 것이다. 따라서 빠르게 해결할 수 있는 알고리즘인 이진 탐색(이분 탐색)을 사용하였다.
기본적인 알고리즘은 아래와 같다.
low=1, high=n*n으로 설정
low <= high 일 동안 while문 루프
mid값 구하기
mid값보다 작거나 같은 수들 구하기 => cnt
cnt값이 목표 인덱스 보다 크거나 같을 경우
mid를 왼쪽으로 옮기기
cnt값이 목표 인덱스 보다 작을 경우
mid를 오른쪽으로 옮기기
루프 탈출 후 low값 출력
[n = 3 , k = 5 인 경우]
array[3][3] | 1 | 2 | 3 |
1 | 1 | 2 | 3 |
2 | 2 | 4 | 6 |
3 | 3 | 6 | 9 |
*mid 값보다 작은 값들의 갯수를 구하는 함수 먼저 구현
ll func(ll x) { // mid보다 작은 수들의 개수를 시간 초과 없이 시간 복잡도 O(n) 으로 구현
ll sum = 0;
for (int i = 1; i <= n; i++){
sum += min(x / i, n);
}
return sum;
}
mid = 5
함수 결과 : 2 + 2 + 1 = 5
k | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
array[k] | 1 | 2 | 3 | 2 | 4 | 6 | 3 | 6 | 9 |
mid 값보다 작은 값들의 갯수 : 5개
알고리즘을 이용하여 코드를 작성하면 전체 소스 코드는 아래와 같다.
/*
low=1, high=n*n으로 설정
low <= high 일 동안 while문 루프
mid값 구하기
mid값보다 작거나 같은 수들 구하기 => cnt
cnt값이 목표 인덱스(K) 보다 크거나 같을 경우
mid를 좀 더 왼쪽으로 옮겨야 한다.
high = mid - 1
cnt값이 목표 인덱스(K) 보다 작을 경우
mid를 좀 더 오른쪽으로 옮겨야 한다.
low = mid + 1
루프 탈출 후 low값 출력
*/
#include <stdio.h>
#define min(a,b) (a) < (b) ? (a) : (b)
#pragma warning(disable:4996)
#define INF 1000000000
typedef long long int ll;
ll n, k;
ll low, high, mid;
ll cnt;
ll func(ll x) { // mid보다 작은 수들의 개수를 시간 초과 없이 시간 복잡도 O(n) 으로 구현
ll sum = 0;
for (int i = 1; i <= n; i++){
sum += min(x / i, n);
}
return sum;
}
int main() {
scanf("%lld%lld", &n, &k);
low = 1;
high = n * n;
k = min((long long)INF, k);
while (low <= high) { // 이진 탐색
mid = (low + high) / 2;
cnt = func(mid);
if (cnt >= k) { // cnt값이 목표 인덱스 보다 크거나 같을 경우
high = mid - 1; // high 값 업데이트
}
else { // cnt값이 목표 인덱스 보다 작을 경우
low = mid + 1; // low 값 업데이트
}
}
printf("%d", low); // 루프 탈출 후 low 값 출력
return 0;
}
이진 탐색의 개념과 시간 복잡도를 줄일 수 있는 방법을 안다면 쉽게 해결 가능한 문제였다.
[1300번]
https://www.acmicpc.net/problem/1300
1300번: K번째 수
세준이는 크기가 N×N인 배열 A를 만들었다. 배열에 들어있는 수 A[i][j] = i×j 이다. 이 수를 일차원 배열 B에 넣으면 B의 크기는 N×N이 된다. B를 오름차순 정렬했을 때, B[k]를 구해보자. 배열 A와 B
www.acmicpc.net
[github]
https://github.com/MinWook6457
MinWook6457 - Overview
MinWook6457 has 18 repositories available. Follow their code on GitHub.
github.com
'알고리즘' 카테고리의 다른 글
[경시대회] 왜 아픈 상처에 소금을 뿌리십니까? (0) | 2024.05.08 |
---|---|
[경시대회] 소믈리에 구름이 (0) | 2024.05.08 |
[백준] 11053번 - 가장 긴 증가하는 부분 수열 (C언어) [Silver2] (0) | 2023.06.02 |
[백준] 1517번 - 버블 소트 (C언어) [Platinum5] (0) | 2023.06.01 |
[백준] 2042번 - 구간 합 구하기 (C언어) [Gold1] (0) | 2023.05.31 |