您的位置:首页 > 编程语言 > Python开发

leetcode 786. K-th Smallest Prime Fraction

2018-03-17 22:23 351 查看

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/q
p < q
[p, q]


输入格式

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


Examples:

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.

A = [1, 7], K = 1

Output: [1, 7]

解释:

由A组成的分数排序:1/7.

第1小的是 1/7.

解答思路

解法一:运用heapq

1.把A的元素按顺序记为p1,p2,p3,⋅⋅⋅,pn(A中有n个元素)。

2.heapq先添加p1pn,p2pn,p3pn,⋅⋅⋅,pn−1pn。

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

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

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

解法二:二分查找

1.把A的元素按顺序记为p1,p2,p3,⋅⋅⋅,pn(A中有n个元素)。

2.取m在[0, 1]取中值,s=∑i=1n−1n−argmaxj{pj≤pim}表示了前s个分数小于m.

3.对m进行二分查找。

4.如果s=K,argmaxi{pipj|j=argmaxj{pj≤pim}},此时的[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<q
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