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. python asyncio as_completed

    #asyncio 没有提供http协议的接口 aiohttp import asyncio import socket from urllib.parse import urlparse async ...

  2. 奥展项目笔记05--域名、端口、Nginx相关知识笔记

    1.我国的电信运营商是默认封闭80端口的. 中国电信屏蔽ADSL用户80端口 只是做应用服务器的话你可以使用别的端口. 80端口电脑上同时有各种各样的程序在运行,他们都需要借助网络来进行通信.例如,你 ...

  3. JavaScript的__proto__、prototype和继承

    JavaScript也是可以“继承”的! 各位看官或是好奇,或是一知半解.什么是prototype,__proto__,constructor.哪种继承方式好.今天就在这交流交流. 什么是protot ...

  4. 车位iou计算

    车位检测中,判断多帧图像检测出的车位是否是同一个车位.计算其IOU. 判断一个点是否在一个四边形内 Approach : Let the coordinates of four corners be ...

  5. C#, CSV,Generic, 泛型,导出

    using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threa ...

  6. C# 实现 奇数偶数排序,奇数在前,偶数在后

    public static void SortByOddAndEven(int []arr) { for (int i = 0; i < arr.Length; i++) { for (int ...

  7. 【机器学习笔记】来吧!解析k-NN

    序: 监督型学习与无监督学习,其最主要区别在于:已知的数据里面有没有标签(作为区别数据的内容). 监督学习大概是这个套路: 1.给定很多很多数据(假设2000个图片),并且给每个数据加上标签(与图片一 ...

  8. C 输入和输出、char类型

    参考链接:https://www.runoob.com/cprogramming/c-input-output.html 标准输入输出头文件stdio.h #include是一个预处理指令,用于引入s ...

  9. python接口上传图片和文件的方法

    import requests def sendImg(img_path, img_name, img_type='image/jpeg'): """ :param im ...

  10. Java学习——String,StringBuffer和StringBuilder

    Java学习——String,StringBuffer和StringBuilder 摘要:本文主要介绍了String字符串在内存中的存储情况,以及StringBuffer和StringBuilder的 ...