Skip to content

Commit 1860545

Browse files
committed
添加 problem 786
1 parent 30bdfad commit 1860545

File tree

3 files changed

+168
-0
lines changed

3 files changed

+168
-0
lines changed
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package leetcode
2+
3+
import (
4+
"sort"
5+
)
6+
7+
// 解法一 二分搜索
8+
func kthSmallestPrimeFraction(A []int, K int) []int {
9+
low, high, n := 0.0, 1.0, len(A)
10+
// 因为是在小数内使用二分查找,无法像在整数范围内那样通过 mid+1 和边界判断来终止循环
11+
// 所以此处根据 count 来结束循环
12+
for {
13+
mid, count, p, q, j := (high+low)/2.0, 0, 0, 1, 0
14+
for i := 0; i < n; i++ {
15+
for j < n && float64(A[i]) > float64(mid)*float64(A[j]) {
16+
j++
17+
}
18+
count += n - j
19+
if j < n && q*A[i] > p*A[j] {
20+
p = A[i]
21+
q = A[j]
22+
}
23+
}
24+
if count == K {
25+
return []int{p, q}
26+
} else if count < K {
27+
low = mid
28+
} else {
29+
high = mid
30+
}
31+
}
32+
}
33+
34+
// 解法二 暴力解法,时间复杂度 O(n^2)
35+
func kthSmallestPrimeFraction1(A []int, K int) []int {
36+
if len(A) == 0 || (len(A)*(len(A)-1))/2 < K {
37+
return []int{}
38+
}
39+
fractions := []Fraction{}
40+
for i := 0; i < len(A); i++ {
41+
for j := i + 1; j < len(A); j++ {
42+
fractions = append(fractions, Fraction{molecule: A[i], denominator: A[j]})
43+
}
44+
}
45+
sort.Sort(SortByFraction(fractions))
46+
return []int{fractions[K-1].molecule, fractions[K-1].denominator}
47+
}
48+
49+
// Fraction define
50+
type Fraction struct {
51+
molecule int
52+
denominator int
53+
}
54+
55+
// SortByFraction define
56+
type SortByFraction []Fraction
57+
58+
func (a SortByFraction) Len() int { return len(a) }
59+
func (a SortByFraction) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
60+
func (a SortByFraction) Less(i, j int) bool {
61+
return a[i].molecule*a[j].denominator < a[j].molecule*a[i].denominator
62+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package leetcode
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
)
7+
8+
type question786 struct {
9+
para786
10+
ans786
11+
}
12+
13+
// para 是参数
14+
// one 代表第一个参数
15+
type para786 struct {
16+
A []int
17+
K int
18+
}
19+
20+
// ans 是答案
21+
// one 代表第一个答案
22+
type ans786 struct {
23+
one []int
24+
}
25+
26+
func Test_Problem786(t *testing.T) {
27+
28+
qs := []question786{
29+
30+
question786{
31+
para786{[]int{1, 2, 3, 5}, 3},
32+
ans786{[]int{2, 5}},
33+
},
34+
35+
question786{
36+
para786{[]int{1, 7}, 1},
37+
ans786{[]int{1, 7}},
38+
},
39+
40+
question786{
41+
para786{[]int{1, 2}, 1},
42+
ans786{[]int{1, 2}},
43+
},
44+
45+
question786{
46+
para786{[]int{1, 2, 3, 5, 7}, 6},
47+
ans786{[]int{3, 7}},
48+
},
49+
}
50+
51+
fmt.Printf("------------------------Leetcode Problem 786------------------------\n")
52+
53+
for _, q := range qs {
54+
_, p := q.ans786, q.para786
55+
fmt.Printf("【input】:%v 【output】:%v\n", p, kthSmallestPrimeFraction(p.A, p.K))
56+
}
57+
fmt.Printf("\n\n\n")
58+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# [786. K-th Smallest Prime Fraction](https://leetcode.com/problems/k-th-smallest-prime-fraction/)
2+
3+
4+
## 题目:
5+
6+
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.
7+
8+
What is the `K`-th smallest fraction considered? Return your answer as an array of ints, where `answer[0] = p` and `answer[1] = q`.
9+
10+
Examples:
11+
Input: A = [1, 2, 3, 5], K = 3
12+
Output: [2, 5]
13+
Explanation:
14+
The fractions to be considered in sorted order are:
15+
1/5, 1/3, 2/5, 1/2, 3/5, 2/3.
16+
The third fraction is 2/5.
17+
18+
Input: A = [1, 7], K = 1
19+
Output: [1, 7]
20+
21+
**Note:**
22+
23+
- `A` will have length between `2` and `2000`.
24+
- Each `A[i]` will be between `1` and `30000`.
25+
- `K` will be between `1` and `A.length * (A.length - 1) / 2`.
26+
27+
28+
## 题目大意
29+
30+
一个已排序好的表 A,其包含 1 和其他一些素数.  当列表中的每一个 p<q 时,我们可以构造一个分数 p/q 。
31+
32+
那么第 k 个最小的分数是多少呢?  以整数数组的形式返回你的答案, 这里 answer[0] = p 且 answer[1] = q.
33+
34+
35+
注意:
36+
37+
- A 的取值范围在 2 — 2000.
38+
- 每个 A[i] 的值在 1 —30000.
39+
- K 取值范围为 1 — A.length * (A.length - 1) / 2
40+
41+
42+
## 解题思路
43+
44+
45+
- 给出一个从小到大排列的有序数组,数组里面的元素都是质数,请找出这个数组中的数组成的真分数从小到大排列,第 K 小的分数。
46+
- 这一题的暴力解法是枚举所有可能的真分数,从小到大排序,输出第 K 小的分数即可。注意排序的时候不能直接用 float 排序,需要转化成分子和分母的结构体进行排序。
47+
- 最优的解法是二分搜索。由于真分数都小于 1,所以二分搜索的范围是 [0,1]。每次二分出来的 mid,需要在数组里面搜索一次,找出比 mid 小的真分数个数。并记录下最大的真分数的分子和分母,动态维护最大真分数的分子和分母。如果比 mid 小的真分数个数小于 K,那么取右区间继续二分,如果比 mid 小的真分数个数大于 K,那么取左区间继续二分。直到正好找到比 mid 小的真分数个数是 K,此时维护的最大真分数的分子和分母即为答案。
48+
- 在已排序的矩阵中寻找最 K 小的元素这一系列的题目有:第 373 题,第 378 题,第 668 题,第 719 题,第 786 题。

0 commit comments

Comments
 (0)