一个已排序好的表 A,其包含 1 和其他一些素数. 当列表中的每一个 p 那么第 k 个最小的分数是多少呢? 以整数数组的形式返回你的答案, 这里 answer[0] = p 且 answer[1] = q. 示例: 注意: 思 路 分 析 : \color{blue}{思路分析:} 思路分析:刚开始可能大家都会想到先把所以的分数构造出来,然后排序,蛋式这种算法效率非常低。看了下提示,说可以使用优先队列,即优先队列中的元素按照分数值递增的顺序排序,我们构造所有的分数并且维持队列的大小等于k,这样队头即是需要求的结果。 然而超时了,这算法的时间复杂度至少是O(n2)级别。
输入: 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
struct cmp {
//自定义排序结构体
bool operator() (const pair<int, int> & a, const pair<int, int> & b) {
return a.first*b.second < b.first*a.second;
}
};
class Solution {
public:
vector<int> kthSmallestPrimeFraction(vector<int>& A, int K) {
int Asize = A.size();
priority_queue<pair<int, int>, vector<pair<int, int>>, cmp> pq;
//构造所有分数
for (int i = 0; i < Asize ; ++i) {
for (int j = 0; j < i; ++j) {
pair<int, int> temp = make_pair(A[j], A[i]);
if (pq.size() < K || myCmp(temp, pq.top())) {//维持队列的大小 == k,并且递减的顺序
pq.push(make_pair(A[j], A[i]));
if (pq.size() > K) {
pq.pop();
}
}
}
}
//最后队列头部就是第k小的元素
return {pq.top().first, pq.top().second}
}
//比较两个分数的大小
static bool myCmp (const pair<int, int> & a, const pair<int, int> & b) {
return a.first * b.second < b.first * a.second;
}
};
然而还有一个提示就是使用二分搜索,我们首先确定left = 0.0, right = 1.0,mid = (left + right) / 2,接着我们寻找比mid小的分数个数cnt,如果cnt == k,说明正好找到了,返回p、q即可,如果 cnt < k,说明mid还比较小,这时增大左边界left = mid,否则缩小右边界right = mid。class Solution {
public:
vector<int> kthSmallestPrimeFraction(vector<int>& A, int K) {
double left = 0, right = 1.0, mid;//二分法三个指针
int p = 0, q = 1, Asize = A.size(), cnt;
while (true) {
double mid = (left + right) / 2.0;
cnt = 0; p = 0;
//A[i]为分子,A[j]为分母,寻找比mid小的分数个数
for (int i = 0, j = 0; i < Asize; ++i) {
while (j < Asize && A[i] > mid * A[j]) {
++j;
}
cnt += Asize - j;//以A[i]为分子,比mid小的分数个数
if (j < Asize && p * A[j] < q * A[i]) {
p = A[i];
q = A[j];
}
}
if (cnt == K) {//当前mid正好是所寻找的结果
return {p, q};
}
else if (cnt < K) {//mid小了,所以右移left
left = mid;
}
else {//mid大了,所以左移right
right = mid;
}
}
}
};