一个已排序好的表 A,其包含 1 和其他一些素数. 当列表中的每一个 p<q 时,我们可以构造一个分数 p/q 。
那么第 k 个最小的分数是多少呢? 以整数数组的形式返回你的答案, 这里 answer[0] = p 且 answer[1] = q.
输入: A = [1, 2, 3, 5], K = 3
输出: [2, 5]
解释:
已构造好的分数,排序后如下所示:
1/5, 1/3, 2/5, 1/2, 3/5, 2/3.
很明显第三个最小的分数是 2/5.
输入: A = [1, 7], K = 1
输出: [1, 7]
注意:
A 长度的取值范围在 2 — 2000.
每个 A[i] 的值在 1 —30000.
K 取值范围为 1 —A.length * (A.length - 1) / 2
方法一:暴力+堆
52/62 TLE…
class Solution {
public:
typedef pair<int, int> pii;
struct cmp{
bool operator()(pii& a, pii& b){
return a.first*b.second < a.second*b.first;
}
};
vector<int> kthSmallestPrimeFraction(vector<int>& A, int K) {
int n=A.size();
priority_queue<pii, vector<pii>, cmp> minQ;
for (int i=0; i<n-1; i++)
for (int j=i+1; j<n; j++) {
minQ.push({A[i], A[j]});
if (minQ.size() > K)
minQ.pop();
}
return {minQ.top().first, minQ.top().second};
}
};
稍微优化了下,还是 58/62 TLE…
class Solution {
public:
typedef pair<int, int> pii;
struct cmp{
bool operator()(pii& a, pii& b){
return a.first*b.second < a.second*b.first;
}
};
vector<int> kthSmallestPrimeFraction(vector<int>& A, int K) {
int n=A.size();
priority_queue<pii, vector<pii>, cmp> minQ;
for (int i=0; i<n-1; i++)
for (int j=i+1; j<n; j++) {
if(minQ.size()<K) {
minQ.push({A[i], A[j]});
} else {
auto& peek = minQ.top();
if (A[i]*peek.second < peek.first*A[j]) {
minQ.pop(), minQ.push({A[i], A[j]});
}
}
}
return {minQ.top().first, minQ.top().second};
}
};
复杂度分析
- Time: O ( n 2 l o g K ) O(n^2logK) O(n2logK),
- Space: O ( K ) O(K) O(K),
方法二:二分
参考别人的思路:用二分在数组 A 中找出小于标定分数 mid = (l+r)/2 的分数的个数 cnt,通过比对 cnt 和 K 的大小来移动左边界 l 和右边界 r
不清楚为什么 l 和 r 不能用 int
class Solution {
public:
vector<int> kthSmallestPrimeFraction(vector<int>& A, int K) {
int n=A.size(); double l=0, r=1;
while (true) {
double mid=(l+r)*0.5;
int cnt=0, a=0, b=1; //cnt统计≤mid的分数的个数
for (int i=0,j=i+1; i<n; i++) {
while (j<n && A[i]>mid*A[j]) j++;
cnt+=n-j;
//此时的 A[i]/A[j] ≤ mid,A[i]/A[j] 还比 a/b 大,可以作为答案
if (j<n && A[i]*b>A[j]*a)
a=A[i], b=A[j];
}
if (cnt==K) {
return {a, b};
} else if (cnt<K) {
l=mid;
} else {
r=mid;
}
}
return {-1, -1};
}
};
复杂度分析
- Time: O ( n l o g n ) O(nlogn) O(nlogn),
- Space: O ( 1 ) O(1) O(1),