0786. K Th Smallest Prime Fraction

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.

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.

题目大意 #

一个已排序好的表 A,其包含 1 和其他一些素数.  当列表中的每一个 p<q 时,我们可以构造一个分数 p/q 。

那么第 k 个最小的分数是多少呢?  以整数数组的形式返回你的答案, 这里 answer[0] = p 且 answer[1] = q.

注意:

  • A 的取值范围在 2 — 2000.
  • 每个 A[i] 的值在 1 —30000.
  • K 取值范围为 1 — A.length * (A.length - 1) / 2

解题思路 #

  • 给出一个从小到大排列的有序数组,数组里面的元素都是质数,请找出这个数组中的数组成的真分数从小到大排列,第 K 小的分数。
  • 这一题的暴力解法是枚举所有可能的真分数,从小到大排序,输出第 K 小的分数即可。注意排序的时候不能直接用 float 排序,需要转化成分子和分母的结构体进行排序。
  • 最优的解法是二分搜索。由于真分数都小于 1,所以二分搜索的范围是 [0,1]。每次二分出来的 mid,需要在数组里面搜索一次,找出比 mid 小的真分数个数。并记录下最大的真分数的分子和分母,动态维护最大真分数的分子和分母。如果比 mid 小的真分数个数小于 K,那么取右区间继续二分,如果比 mid 小的真分数个数大于 K,那么取左区间继续二分。直到正好找到比 mid 小的真分数个数是 K,此时维护的最大真分数的分子和分母即为答案。
  • 在已排序的矩阵中寻找最 K 小的元素这一系列的题目有:第 373 题,第 378 题,第 668 题,第 719 题,第 786 题。

代码 #


package leetcode

import (
	"sort"
)

// 解法一 二分搜索
func kthSmallestPrimeFraction(A []int, K int) []int {
	low, high, n := 0.0, 1.0, len(A)
	// 因为是在小数内使用二分查找,无法像在整数范围内那样通过 mid+1 和边界判断来终止循环
	// 所以此处根据 count 来结束循环
	for {
		mid, count, p, q, j := (high+low)/2.0, 0, 0, 1, 0
		for i := 0; i < n; i++ {
			for j < n && float64(A[i]) > float64(mid)*float64(A[j]) {
				j++
			}
			count += n - j
			if j < n && q*A[i] > p*A[j] {
				p = A[i]
				q = A[j]
			}
		}
		if count == K {
			return []int{p, q}
		} else if count < K {
			low = mid
		} else {
			high = mid
		}
	}
}

// 解法二 暴力解法,时间复杂度 O(n^2)
func kthSmallestPrimeFraction1(A []int, K int) []int {
	if len(A) == 0 || (len(A)*(len(A)-1))/2 < K {
		return []int{}
	}
	fractions := []Fraction{}
	for i := 0; i < len(A); i++ {
		for j := i + 1; j < len(A); j++ {
			fractions = append(fractions, Fraction{molecule: A[i], denominator: A[j]})
		}
	}
	sort.Sort(SortByFraction(fractions))
	return []int{fractions[K-1].molecule, fractions[K-1].denominator}
}

// Fraction define
type Fraction struct {
	molecule    int
	denominator int
}

// SortByFraction define
type SortByFraction []Fraction

func (a SortByFraction) Len() int      { return len(a) }
func (a SortByFraction) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a SortByFraction) Less(i, j int) bool {
	return a[i].molecule*a[j].denominator < a[j].molecule*a[i].denominator
}


⬅️上一页

下一页➡️

Calendar Sep 6, 2020
Edit Edit this page
本站总访问量:  次 您是本站第  位访问者