786. K-th Smallest Prime Fraction

探讨了一种算法,用于找到一个包含1和其他若干素数的有序列表中,第K小的比例p/q,其中p和q分别来自列表中的两个不同元素。提供了两种方法:暴力法和二分搜索法,并详细解释了二分搜索法如何优化时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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.

Approach #1: brute force.[Time Limit Exceeded]

class Solution {
public:
    vector<int> kthSmallestPrimeFraction(vector<int>& A, int K) {
        int n = A.size();
        vector<pair<int, int>> temp;
        vector<int> ans;
        for (int i = 0; i < n; ++i) {
            for (int j = i+1; j < n; ++j) {
                temp.push_back({A[i], A[j]});
            }
        }
        sort(temp.begin(), temp.end(), cmp);
        ans.push_back(temp[K-1].first);
        ans.push_back(temp[K-1].second);
        return ans;
    }
    
    static bool cmp (pair<int, int> a, pair<int, int> b) {
        return (double)a.first/a.second < (double)b.first/b.second;
    }
};

 

Approach #2: Binary Search.

class Solution {
public:
    vector<int> kthSmallestPrimeFraction(vector<int>& A, int K) {
        int n = A.size();
        double l = 0.0, r = 1.0;
        while (l < r) {
            double m = (l + r) / 2;
            double max_f = 0.0;
            int total = 0;
            int p, q;
            int j = 1;
            for (int i = 0; i < n-1; ++i) {
                while (j < n && A[i] > m * A[j]) ++j;
                total += (n - j);
                if (j == n) break;
                double f = static_cast<double>(A[i]) / A[j];
                if (f > max_f) {
                    p = i;
                    q = j;
                    max_f = f;
                }
            }
            if (total == K) return {A[p], A[q]};
            else if (total < K) l = m;
            else r = m;
        }
        return {};
    }
};

Runtime: 12 ms, faster than 83.88% of C++ online submissions for K-th Smallest Prime Fraction.

 

Analysis:

1. why use static_cast<>?

In short:

  1. static_cast<>() gives you a compile time checking ability, C-Style cast doesn't.
  2. static_cast<>() can be spotted easily anywhere inside a C++ source code; in contrast, C_Style cast is harder to spot.
  3. Intentions are conveyed much better using C++ casts.

More Explanation:

The static cast performs conversions between compatible types. It is similar to the C-style cast, but is more restrictive. For example, the C-style cast would allow an integer pointer to point to a char.

char c = 10;       // 1 byte
int *p = (int*)&c; // 4 bytes

Since this results in a 4-byte pointer pointing to 1 byte of allocated memory, writing to this pointer will either cause a run-time error or will overwrite some adjacent memory.

*p = 5; // run-time error: stack corruption

In contrast to the C-style cast, the static cast will allow the compiler to check that the pointer and pointee data types are compatible, which allows the programmer to catch this incorrect pointer assignment during compilation.

int *q = static_cast<int*>(&c); // compile-time error

 

2. In this way we make m as a flag (range is from 0 to 1),  we can count the numbers which elements less than m. when if m == K we return {A[p], A[q]} , else if m > K => r = m; else l = m

we can use a matrix to instore the A[i] / A[j], but in order to reduce the time complexity  we can use under code to realize.

  
for (int i = 0; i < n-1; ++i)
  while (j < n && A[i] > m * A[j]) ++j;

for every loop j can be using repeatedly, because when i increase, in order to make A[i] > m * A[j], j must bigger than last loop.

 

转载于:https://www.cnblogs.com/ruruozhenhao/p/9936650.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值