LeetCode 786: K-th Smallest Prime Fraction

一:题目描述

1.英文描述:

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] = p and 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.

2.中文描述:

786 第 K 个最小的素数分数

一个已排序好的表 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。

二:算法分析

思路:
初始时left = 0,right = 1,在区间[left,right]使用二分查找找出一个 mid,记录小于 mid 的分数 好有 count 个,并且记录在mid左边其中最大的一个分数 p/q。如果count == K 时就说明此时在mid之前的数刚好有K个,此时则返回 [p, q]。若 count < K 时则缩小区间为[mid,right],然后重新定义mid,然 后在按照上述循环。若count > K 时则缩小区间为[left,mid],然后重新定义mid,然后在按照上述循 环。其主要思想就是要用二分查找的思想,找到一个数使得小于其的数恰好为K个,然后返回其中 最大的即可。

三:代码

#include<iostream>
#include<vector>
using namespace std;
class Solution{            //二分查找       
public:
    vector<int> kthSmallestPrimeFraction(vector<int>& A, int K) 
    {
        double left = 0, right = 1.0, mid;
        int p = 0;
        int q = 1;
        int Asize = A.size();
        int count; 
        while (true) 
        {
            double mid = (left + right) / 2.0;
            count = 0; 
            p = 0;
            for (int i = 0, j = i+1; i < Asize; ++i) 
            {
                while (j < Asize && mid < (double)A[i]/(double)A[j]  )
                {
                    ++j;
                }
                count += Asize - j;		//记录在 mid 之前数的个数
                if (j < Asize && (double)p/(double)q < (double)A[i]/(double)A[j]) 	//记录此时在mid之前的最大的 p / q
                {
                    p = A[i];
                    q = A[j];
                }
            }
            if (count == K) 		//若相等就返回此时的p q
            {
                return {p, q};
            }
            else if (count < K)  	//若 count < K 就缩小区间为[mid,right]
            {
                left = mid;
            }
            else                	//若 count > K 就缩小区间为[left,mid]
            {
                right = mid;
            }
        }
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值