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]
提示:
- 2 <= arr.length <= 1000
- 1 <= arr[i] <= 3 * 10410^4104
- arr[0] == 1
- arr[i] 是一个 素数 ,i > 0
- arr 中的所有数字 互不相同 ,且按 严格递增 排序
- 1 <= k <= arr.length * (arr.length - 1) / 2
解题思路
题目需要求得第 k 个最小的分数,而分数定义为每对满足 0 < i < j < arr.length 的 i 和 j ,得到的arr[i] / arr[j] ,因为数组arr是按递增顺序排序的,因此分数都是小于0的数字。为了避免浮点数的精度丢失,当我们比较当我们比较两个分数 ab\dfrac{a}{b}ba和 cd\dfrac{c}{d}dc时,我们可以使用:a×d<b×ca \times d < b \times ca×d<b×c来替代 $\dfrac{a}{b} < \dfrac{c}{d} $的判断,二者是等价的,这样就可以避免计算机浮点数丢失造成的问题。因此我们在排序中需要根据上述规则进行自定义的排序,然后选出第k个最小的分数。
代码
class Solution {
public:vector<int> kthSmallestPrimeFraction(vector<int> &arr, int k) {vector<pair<int, int>> cnt;for (int i = 0; i < arr.size(); ++i) {for (int j = i - 1; j >= 0; --j) {cnt.emplace_back(arr[j], arr[i]);}}sort(cnt.begin(), cnt.end(), [&](const auto &x, const auto &y) {return x.first * y.second < x.second * y.first;});return {cnt[k-1].first,cnt[k-1].second};}
};