786. 第 K 个最小的素数分数
给你一个按递增顺序排序的数组 arr
和一个整数 k
。数组 arr
由 1
和若干 素数 组成,且其中所有整数互不相同。
对于每对满足 0 < i < j < arr.length
的 i
和 j
,可以得到分数 arr[i] / arr[j]
。
那么第 k
个最小的分数是多少呢? 以长度为 2 的整数数组返回你的答案, 这里 answer[0] == arr[i]
且 answer[1] == arr[j]
。
示例 1:输入:arr = [1,2,3,5], k = 3
输出:[2,5]
解释:已构造好的分数,排序后如下所示:
1/5, 1/3, 2/5, 1/2, 3/5, 2/3
很明显第三个最小的分数是 2/5
示例 2:输入:arr = [1,7], k = 1
输出:[1,7]
解法一:指定规则排序
class Solution:
def kthSmallestPrimeFraction(self, arr: List[int], k: int) -> List[int]:
def cmp(x: Tuple[int, int], y: Tuple[int, int]) -> int:
return -1 if x[0] * y[1] < x[1] * y[0] else 1
n = len(arr)
ans = list()
for i in range(n):
for j in range(i+1, n):
ans.append((arr[i], arr[j]))
# 自定义排序规则
ans.sort(key=(cmp_to_key(cmp)))
return list(ans[k-1])
时间复杂度:O(n n log n),空间复杂度:O(n * n)
解法二:二分查找+双指针
class Solution:
def kthSmallestPrimeFraction(self, arr: List[int], k: int) -> List[int]:
n = len(arr)
left, right = 0.0, 1.0
while True:
mid = (left + right) / 2
i, count = -1, 0
x, y = 0, 1
for j in range(1, n):
while arr[i+1] / arr[j] < mid:
i += 1
if arr[i] * y > arr[j] * x:
x, y = arr[i], arr[j]
count += i + 1
if count == k:
return [x, y]
elif count > k:
right = mid
elif count < k:
left = mid
时间复杂度:O(n * logC),空间复杂度:O(1)