A sorted list A contains 1, plus some number of primes.  Then, for every p < q in the list, we consider the fraction p/q.

What is the K-th smallest fraction considered?  Return your answer as an array of ints, where answer[0] = pand answer[1] = q.

Examples:
Input: A = [1, 2, 3, 5], K = 3
Output: [2, 5]
Explanation:
The fractions to be considered in sorted order are:
1/5, 1/3, 2/5, 1/2, 3/5, 2/3.
The third fraction is 2/5. Input: A = [1, 7], K = 1
Output: [1, 7]

Note:

  • A will have length between 2 and 2000.
  • Each A[i] will be between 1 and 30000.
  • K will be between 1 and A.length * (A.length - 1) / 2.

这道题给了我们一个有序数组,里面是1和一些质数,说是对于任意两个数,都可以组成一个 [0, 1] 之间分数,让求第K小的分数是什么,题目中给的例子也很好的说明了题意。那么最直接暴力的解法就是遍历出所有的分数,然后再进行排序,返回第K小的即可。但是这种无脑暴力搜索的方法 OJ 是不答应的,无奈,只能想其他的解法。由于数组是有序的,所以最小的分数肯定是由第一个数字和最后一个数字组成的,而接下来第二小的分数就不确定是由第二个数字和最后一个数字组成的,还是由第一个数字跟倒数第二个数字组成的。这里用一个最小堆来存分数,那么每次取的时候就可以将最小的分数取出来,由于前面说了,不能遍历所有的分数都存入最小堆,那么该怎么办呢,可以先存n个,哪n个呢?其实就是数组中的每个数字都和最后一个数字组成的分数。由于需要取出第K小的分数,那么在最小堆中取K个分数就可以了,第一个取出的分数就是那个由第一个数字和最后一个数字组成的最小的分数,然后就是精髓所在了,此时将分母所在的位置前移一位,还是和当前的分子组成新的分数,这里即为第一个数字和倒数第二个数字组成的分数,存入最小堆中,那么由于之前已经将第二个数字和倒数第一个数字组成的分数存入了最小堆,所以不用担心第二小的分数不在堆中,这样每取出一个分数,都新加一个稍稍比取出的大一点的分数,这样取出了第K个分数即为所求,参见代码如下:

解法一:

class Solution {
public:
vector<int> kthSmallestPrimeFraction(vector<int>& A, int K) {
priority_queue<pair<double, pair<int, int>>> q;
for (int i = ; i < A.size(); ++i) {
q.push({-1.0 * A[i] / A.back(), {i, A.size() - }});
}
while (--K) {
auto t = q.top().second; q.pop();
--t.second;
q.push({-1.0 * A[t.first] / A[t.second], {t.first, t.second}});
}
return {A[q.top().second.first], A[q.top().second.second]};
}
};

其实这道题比较经典的解法是用二分搜索法 Binary Search,使用的二分搜索法是博主归纳总结帖 LeetCode Binary Search Summary 二分搜索法小结 中的第四种,即二分法的判定条件不是简单的大小关系,而是可以抽离出子函数的情况,下面来看具体怎么弄。这种高级的二分搜索法在求第K小的数的时候经常使用,比如 Kth Smallest Element in a Sorted MatrixKth Smallest Number in Multiplication Table,和 Find K-th Smallest Pair Distance 等。思路都是用 mid 当作 candidate,然后统计小于 mid 的个数 cnt,和K进行比较,从而确定折半的方向。这道题也是如此,mid 为候选的分数值,刚开始时是 0.5,然后需要统计出不大于 mid 的分数都个数 cnt,同时也需要找出最接近 mid 的分数,当作返回的候选值,因为一旦 cnt 等于K了,直接将这个候选值返回即可,这个候选值分数是由p和q来表示的,其中p表示分子,初始化为0,q表示分母,初始化为1(因为除数不能为0),在内部的 while 循环退出时,分数 A[i]/A[j] 就是最接近 mid 的候选者,此时假如 p/q 要小于 A[i]/A[j],就要分别更新p和q。否则如果 cnt 小于K,说明应该增大一些 mid,将 left 赋值为 mid,反之如果 cnt 大于K,需要减小 mid,将 right 赋值为 mid,参见代码如下:

解法二:

class Solution {
public:
vector<int> kthSmallestPrimeFraction(vector<int>& A, int K) {
double left = , right = ;
int p = , q = , cnt = , n = A.size();
while (true) {
double mid = left + (right - left) / 2.0;
cnt = ; p = ;
for (int i = , j = ; i < n; ++i) {
while (j < n && A[i] > mid * A[j]) ++j;
cnt += n - j;
if (j < n && p * A[j] < q * A[i]) {
p = A[i];
q = A[j];
}
}
if (cnt == K) return {p, q};
if (cnt < K) left = mid;
else right = mid;
}
}
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/786

类似题目:

Find K Pairs with Smallest Sums

Kth Smallest Element in a Sorted Matrix

Kth Smallest Number in Multiplication Table

Find K-th Smallest Pair Distance

参考资料:

https://leetcode.com/problems/k-th-smallest-prime-fraction/

https://leetcode.com/problems/k-th-smallest-prime-fraction/discuss/115531/C++-9lines-priority-queue

https://leetcode.com/problems/k-th-smallest-prime-fraction/discuss/115819/Summary-of-solutions-for-problems-%22reducible%22-to-LeetCode-378

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] 786. K-th Smallest Prime Fraction 第K小的质分数的更多相关文章

  1. [LeetCode] K-th Smallest Prime Fraction 第K小的质分数

    A sorted list A contains 1, plus some number of primes.  Then, for every p < q in the list, we co ...

  2. 786. K-th Smallest Prime Fraction

    A sorted list A contains 1, plus some number of primes.  Then, for every p < q in the list, we co ...

  3. [Swift]LeetCode786. 第 K 个最小的素数分数 | K-th Smallest Prime Fraction

    A sorted list A contains 1, plus some number of primes.  Then, for every p < q in the list, we co ...

  4. [LeetCode] 719. Find K-th Smallest Pair Distance 找第K小的数对儿距离

    Given an integer array, return the k-th smallest distance among all the pairs. The distance of a pai ...

  5. Java实现 LeetCode 786 第 K 个最小的素数分数(大小堆)

    786. 第 K 个最小的素数分数 一个已排序好的表 A,其包含 1 和其他一些素数. 当列表中的每一个 p<q 时,我们可以构造一个分数 p/q . 那么第 k 个最小的分数是多少呢? 以整数 ...

  6. 【LeetCode】1022. Smallest Integer Divisible by K 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...

  7. 【LeetCode】230. 二叉搜索树中第K小的元素 Kth Smallest Element in a BST

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 公众号:负雪明烛 本文关键词:算法题,刷题,Leetcode, 力扣,二叉搜索树,BST ...

  8. 【leetcode】378. Kth Smallest Element in a Sorted Matrix(TOP k 问题)

    Given an n x n matrix where each of the rows and columns is sorted in ascending order, return the kt ...

  9. Leetcode 1015. Smallest Integer Divisible by K

    思路显然是暴力枚举. 但是两个问题: 1.当1的位数非常大时,模运算很费时间,会超时. 其实每次不用完全用'11111...'来%K,上一次的余数*10+1后再%K就行. 证明: 令f(n)=1111 ...

随机推荐

  1. oracle中如何更改一个表的一个字段属性(名称,类型)

    修改字段的属性,名称方法 --修改某一个字段的类型,当该字段不为null时alter table 表名add 字段NUMBER(11,0) default 0 not null;--添加表一个字段 A ...

  2. POJ 2594 (传递闭包 + 最小路径覆盖)

    题目链接: POJ 2594 题目大意:给你 1~N 个点, M 条有向边.问你最少需要多少个机器人,让它们走完所有节点,不同的机器人可以走过同样的一条路,图保证为 DAG. 很明显是 最小可相交路径 ...

  3. dbvisualizer客户端执行创建存储过程或自定义函数语句的方法

    DBVisualizer这个数据库客户端工具,如果要执行存储过程或函数的话,需要在创建存储过程或函数的语句的最前面和末尾分别加上[--/]和[/]符号. --/ CREATE FUNCTION B22 ...

  4. 云原生生态周报 Vol.9| K8s v1.15 版本发布

    本周作者 | 衷源.心贵 业界要闻 1.Kubernetes Release v1.15 版本发布,新版本的两个主题是持续性改进和可扩展性.(https://github.com/kubernetes ...

  5. [Docker] Win10中安装Docker并运行Nginx镜像

    一.安装Docker 进入官网:https://www.docker.com/products/docker-desktop 可能需要先注册登录,很简单的. 点击 Download Desktop f ...

  6. Solr的知识点学习

    Solr单机版的安装与使用 1.Solr单机版的安装与使用,简单写了如何进行Solr的安装与使用.那么很多细节性问题,这里进行简单的介绍.我使用的是Solr与Tomcat整合配置. 2.什么是Solr ...

  7. .NET使用本地Outlook邮箱指定邮箱用户名和密码发送邮件

    1.添加Microsoft.Office.Interop.Outlook引用 2.封装发送邮件方法 using System; using System.Configuration; using Sy ...

  8. 【微信原生支付】服务商模式-小微商户专属接口:小微商户新增对应APPID关联API

    文档地址:https://pay.weixin.qq.com/wiki/doc/api/xiaowei.php?chapter=20_3&index=3 这个接口比较特殊不需要nonce_st ...

  9. ios视频网盘

    http://pan.baidu.com/share/home?uk=1711799154#category/type=0

  10. Spring Cloud Netflix之Eureka服务消费者

    Eureka服务消费者介绍 Eureka服务消费者用于发现服务和消费服务,发现服务通过Eureka Client完成,消费服务通过Ribbon完成,以实现负载均衡.在实际项目中,一个服务往往同时是服务 ...