K번째 수 - 1300
[Gold II] K번째 수 - 1300
분류 1️⃣
이분 탐색(binary_search), 매개 변수 탐색(parametric_search)
문제 설명 2️⃣
세준이는 크기가 N×N인 배열 A를 만들었다. 배열에 들어있는 수 A[i][j] = i×j 이다. 이 수를 일차원 배열 B에 넣으면 B의 크기는 N×N이 된다. B를 오름차순 정렬했을 때, B[k]를 구해보자.
배열 A와 B의 인덱스는 1부터 시작한다.
입력 3️⃣
첫째 줄에 배열의 크기 N이 주어진다. N은 105보다 작거나 같은 자연수이다. 둘째 줄에 k가 주어진다. k는 min(109, N2)보다 작거나 같은 자연수이다.
출력 4️⃣
B[k]를 출력한다.
풀이 🔓
예시로 n은 3이라고 하면 배열 A는
1 | 2 | 3 |
2 | 4 | 6 |
3 | 6 | 9 |
배열 B는 크기가 9인 아래 형태의 일차원 배열이다.
1 | 2 | 2 | 3 | 3 | 4 | 6 | 6 | 9 |
이때 k는 7이라고 하면
❗ | ||||||||
1 | 2 | 2 | 3 | 3 | 4 | 6 | 6 | 9 |
6을 가리키게 된다.
일단 배열은 크기 N이 10^5 이므로 N^2인 시간복잡도 알고리즘은 사용할 수 없고, 배열 A를 직접 만드는 것은 메모리 초과이다.(배열 크기 : N^10) 이분탐색을 사용하는데 배열 A를 직접 만들지 않는다.
규칙을 찾아보자면 임의의 수 mid보다 작거나 같은 수의 개수를 구하는 식을 찾을 수 있다.
배열 A의 각 행은 구구단의 1단, 2단, 3단 식이기 때문에 (mid/행번호)는 그 행에서 구하고자 하는 개수(나중에 이 개수들을 다 더하여 배열 B의 k번째 인덱스에 도달할 수 있는지 판단)
단, (mid/행번호)가 N보다 클 경우에는 개수는 N이다
예시) 임의의 수 mid를 4라고 했을 때, 1행은 4/1 = 4 이지만 N = 3보다 크므로 3개이며 4/2 = 2 2행은 2개, 4/3 = 1 로 3행은 1개이다
코드 📃
# 1, 2, 3
# 2, 4, 6
# 3, 6, 9
# 1, 2, 2, 3, 3, 4, 6, 6, 9
n = int(input())
k = int(input())
left = 1
right = k # B[k]가 k보다 큰 수는 나올 수가 없음
while left <= right :
mid = (left+right)//2
count = 0
for i in range(1, n+1):
count += min(mid//i, n)
if count < k:
left = mid + 1
else:
right = mid - 1
print(left)
의문 (?)
근데 만약 k가 8이면 즉, 8번 째수가 7, 8이 아니고 6임을 어떻게 알 지??
- 1 이하의 수는 1개
- 2 이하의 수는 3개
- 3 이하의 수는 5개
- 4 이하의 수는 6개
- 6 이하의 수는 8개
- 7 이하의 수는 8개
- 8 이하의 수는 8개
- 9 이하의 수는 9개
6을 보면, 6 이하의 수는 8개 이지만, 4 이하의 수는 6이다. 또 7을 보면, 7이하의 수는 8개이지만, 6이하의 수 역시 8개다. 이 말은 7은 존재하지 않기때문이다 (만약 7이 존재하면 7이하의수에서 7은 포함이 되어 갯수를 더 했을 거니깐) 8을 봐도 8이하의 수는 8개이지만, 7이하의 수 역시 8개 따라서 8도 존재 x 그래서 보통 이분탐색의 마지막에는 mid를 출력하지만 left를 출력한 것도 같은 원리였다!!
댓글남기기