📅  最后修改于: 2023-12-03 15:27:35.242000             🧑  作者: Mango
我们有一个整数数组,其中的元素满足 $0 \le A[i] \le 10^9$ 。我们将两个元素 $A[i]$ 和 $A[j]$ 成为一个比率分数对,当且仅当 $i < j$ 且 $A[i]$ 和 $A[j]$ 是整数的互质数(也就是它们的最大公约数为 1)。特别地,给定数组中相同元素不能成为一个比率分数对。
请你返回数组中最大的比率分数对计数。如果不存在这样的一对数字,返回 0 。
我们可以通过枚举所有比率分数对,来计算能够构成比率分数对的元素数量,但时间复杂度将会是 $O(n^2)$,无法通过本题。
我们需要寻找其他的解法。根据互质数的求法,我们可以使用辗转相除法来计算两个数的最大公约数。这个算法时间复杂度是 $O(\log{\min(a,b)})$。 当我们求出两个数的最大公约数后,就可以判断它们是否构成比率分数对了。
考虑到每个数可能会有多个互质的元素,我们可以使用哈希表来存储每个元素对应的所有互质数。具体的,我们使用一个哈希表 $hashmap$,其中键为元素 $a$,值为集合 $S$,集合 $S$ 中存储所有与元素 $a$ 互质的元素。哈希表可以在 $O(1)$ 时间内查找一个键对应的值。
在建立好哈希表后,我们可以遍历哈希表,对于每一个键值对 $(a,S)$,我们使用 $dp(i,a)$ 表示数列 $A_{1 \dots i}$ 中以 $a$ 为结尾的能够构成比率分数对的最长子序列的长度。我们将最终结果 $ans$ 定义为所有 $dp(i,a)$ 中的最大值。
对于动态规划的状态转移方程,我们可以考虑枚举数列中除 $a$ 外的最后一个元素 $b$(可以通过哈希表来获取 $a$ 的所有互质元素),并检查 $dp(i-1,b)$ 是否存在。如果 $dp(i-1,b)$ 存在,那么以 $a$ 结尾的能够构成比率分数对的最长子序列的长度就是 $dp(i-1,b)+1$。如果 $dp(i-1,b)$ 不存在,则以 $a$ 结尾的能够构成比率分数对的最长子序列的长度就是 1。最终 $dp(i,a)$ 的值就是所有枚举的值中的最大值。
根据上述方程,时间复杂度为 $O(n^2 \log{V})$,其中 $V$ 为数组中最大的元素值。空间复杂度也为 $O(n^2 \log{V})$。
from collections import defaultdict
def gcd(a, b):
if b == 0:
return a
return gcd(b, a % b)
def maxScore(nums):
n = len(nums)
dp = defaultdict(int)
hashmap = defaultdict(set)
for i in range(n):
for j in range(i):
if gcd(nums[i], nums[j]) == 1:
hashmap[nums[i]].add(nums[j])
hashmap[nums[j]].add(nums[i])
ans = 0
for a in hashmap:
dp[(1, a)] = 1
for i in range(2, n+1):
for b in hashmap[a]:
if (i-1, b) in dp:
dp[(i, a)] = max(dp[(i, a)], dp[(i-1, b)]+1)
ans = max(ans, max(dp.values()))
return ans
该代码为 Python 代码。