这道题第一眼看很简单,而且数据量也不大,才2000,以为枚举所有可能的结果然后sort一边就可以解决了,很显然这是一个O(n**2)的解法,但是以做OJ题目的经验来看,假设1s的时限都是充裕的,但是没想到写了一发交上去竟然TLE,百思不得其解,最后联想到之前做过一道合并Set且保留其中前K个数的题目,用优先队列把这道题给A了,再次吐槽一下LeetCode上看不到时限(还是我的姿势不对hhh)。
思路:就是先将所有的 -1 / A[i] (0 < i < A.size())加入到优先队列中,这只是为了,肯定能够得到1 / A[n - 1]肯定是最小值,然后只要将每次从优先队列中取到的值稍微变大一点,然后再次加入到中,这样取K次就可以得到结果了,至于怎么把一个数稍微变大呢,作为一个分数,要么增大分子,要么减小分母,可以证明增大分子更小(乘一下就可以证明了),还要注意的一点就是如果分子已经是A[n - 1]了,那就不能再增大了,好了,这样就可以解决这道题了hhh
代码:
class Solution {
public:
typedef pair<int, int> P;
typedef pair<double, P> ele;
vector<int> kthSmallestPrimeFraction(vector<int>& A, int K) {
priority_queue<ele> que;
for(int i = 1; i < A.size(); ++i)
que.push(ele(-1.0 / A[i], P(0, i)));
ele ans;
while(K--)
{
ans = que.top();
que.pop();
P p = ans.second;
/*if(p.first >= A.size() - 1 || A[p.first + 1] * A[p.second - 1] > A[p.first] * A[p.second])
que.push(ele(-1.0 * A[p.first] / A[p.second - 1], P(p.first, p.second - 1)));
else
que.push(ele(-1.0 * A[p.first + 1] / A[p.second], P(p.first + 1, p.second)));*/
//可以证明A[p.first + 1] * A[p.second - 1] < A[p.first] * A[p.second]在本题这种始终成立
if(p.first < A.size() - 1)
que.push(ele(-1.0 * A[p.first + 1] / A[p.second], P(p.first + 1, p.second)));
}
vector<int> res;
res.push_back(A[ans.second.first]);
res.push_back(A[ans.second.second]);
return res;
}
};