leetcode 786. K-th Smallest Prime Fraction

leetcode 786. K-th Smallest Prime Fraction

  • leetcode 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 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.

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.

Difficulty: hard
786. K-th Smallest Prime Fraction


中文描述
给你一个包含1在内的,排好序的素数列表,找出第K小的分数p/qp < q[p, q]


输入格式
输入一个列表A,列表素数的集合。K表示需要第k小的。


Examples:

  1. Input: A = [1, 2, 3, 5], K = 3
    Output: [2, 5]
    解释:
    由A组成的分数排序:1/5, 1/3, 2/5, 1/2, 3/5, 2/3.
    第3小的是 2/5.

  2. A = [1, 7], K = 1
    Output: [1, 7]
    解释:
    由A组成的分数排序:1/7.
    第1小的是 1/7.


解答思路

  • 解法一:运用heapq

    1.把A的元素按顺序记为 p1p2p3pn A中有 n 个元素)。

    2.heapq先添加 p1pnp2pnp3pnpn1pn

    3.每次从heapq弹出最小的元素,比如第一次为 p1pn ,然后heapq加入 p1pn1 (加入 pipj1 时需要 i>j1 ,)。

    4.重复K次步骤3,得到最后结果。

    5.复杂度估计 O(Klog(n))

  • 解法二:二分查找

    1.把A的元素按顺序记为 p1p2p3pn A中有 n 个元素)。

    2.取 m 在[0, 1]取中值, s=i=1n1nargmaxj{pjpim} 表示了前 s 个分数小于 m .

    3.对 m 进行二分查找。

    4.如果 s=K argmaxi{pipj|j=argmaxj{pjpim}} ,此时的 [i,j] 就是最后答案。

    5.复杂度估计 O(αnlog(n))α 为二分查找的次数


代码

解法一,速度超慢= =,

class Solution(object):
    def kthSmallestPrimeFraction(self, A, K):
        """
        :type A: List[int]
        :type K: int
        :rtype: List[int]
        12785 ms
        """
        import heapq
        l = len(A) - 1
        h = []
        for i in range(l):
            # 先往把每个元素的最小值加入heapq中,heapq中的每个元素第一位表示p/q的值,第二个表示p在A中的索引,第三位表示q在A中的索引
            heapq.heappush(h, (A[i] / float(A[l]), i, l))
        # 一个个查找
        while K > 0:
            # 输出最小的一个
            min_one = heapq.heappop(h)
            # 添加保持min_one的p不变,q选择的索引 + 1,并且保证p
            if min_one[2] - 1 > min_one[1]:
                new_l = min_one[2] - 1
                heapq.heappush(h, (A[min_one[1]] / float(A[new_l]), min_one[1], new_l))
            K -= 1
        return [A[min_one[1]], A[min_one[2]]]

解法二,参考了其它人写的代码详细请见Python solution using Binary Search,速度快了 n 倍:

class Solution(object):
    def kthSmallestPrimeFraction(self, A, K):
        """
        :type A: List[int]
        :type K: int
        :rtype: List[int]
        440ms 只用于python3
        """
        import bisect
        l, r, N = 0, 1, len(A)
        while True:
            m = (l + r) / 2
            # A[i] / A[j] = m --> A[i] / m = A[j],所以通过每个A[i] / m 在通过二分查找可以找比A[j]小的个数
            border = [bisect.bisect(A, A[i] / m) for i in range(N)]
            # 然后我们用 N-比A[j]小的个数 就是所有不小于A[j]的个数,然后对所有A[j]求和
            cur = sum(N - i for i in border)
            if cur > K:
                r = m
            elif cur < K:
                l = m
            else:
                # 找到这个位置之后,把所有可能最大的那个找出来就是最后答案
                return max([(A[i], A[j]) for i, j in enumerate(border) if j < N], key=lambda x: x[0] / x[1])

你可能感兴趣的:(leetcode,python,Binary,Search,heapq)