Q1、数组的最大因子得分
1、题目描述
给你一个整数数组 nums
。
因子得分 定义为数组所有元素的最小公倍数(LCM)与最大公约数(GCD)的 乘积。
在 最多 移除一个元素的情况下,返回 nums
的 最大因子得分。
注意,单个数字的 LCM
和 GCD
都是其本身,而 空数组 的因子得分为 0。
2、解题思路
为了解决这个问题,我们将使用 前缀和后缀数组 的方法,动态计算移除每个元素后的因子得分。
-
数学性质
-
单个数字的 GCD 和 LCM:
- 对于单个数字
x
,其GCD
和LCM
都是x
,因此因子得分为 x × x = x 2 x \times x = x^2 x×x=x2。
- 对于单个数字
-
空数组的 GCD 和 LCM:
- 空数组的 GCD 和 LCM 均为 0,因此因子得分为 0。
-
GCD 和 LCM 的计算公式:
-
最大公约数(GCD):
gcd(a, b)
。 -
最小公倍数(LCM):
lcm(a, b) = a / gcd(a, b) * b
。
-
-
-
前缀和后缀数组
为了高效地计算移除每个元素后的 GCD 和 LCM,我们使用前缀和后缀数组:
- 后缀数组:
sufGCD[i]
表示从索引i
到数组末尾所有元素的 GCD。sufLCM[i]
表示从索引i
到数组末尾所有元素的 LCM。
- 前缀变量:
preGCD
表示从数组开头到当前索引的 GCD。preLCM
表示从数组开头到当前索引的 LCM。
利用前缀和后缀信息,我们可以在 O(1) 的时间内计算移除某个元素后的剩余数组的 GCD 和 LCM。
- 后缀数组:
-
动态更新因子得分
-
对于每个索引 i:
-
计算移除元素
nums[i]
后,剩余数组的 GCD 和 LCM: $\text{remainingGCD} = \text{gcd(preGCD, sufGCD[i + 1])} $
remainingLCM = lcm(preLCM, sufLCM[i + 1]) \text{remainingLCM} = \text{lcm(preLCM, sufLCM[i + 1])} remainingLCM=lcm(preLCM, sufLCM[i + 1])
-
更新最大因子得分:
maxFactorScore = max ( maxFactorScore , remainingGCD × remainingLCM ) \text{maxFactorScore} = \max(\text{maxFactorScore}, \text{remainingGCD} \times \text{remainingLCM}) maxFactorScore=max(maxFactorScore,remainingGCD×remainingLCM)
-
更新前缀 GCD 和前缀 LCM。
-
3、代码实现
class Solution {
public:long long maxScore(vector<int>& nums) {int n = nums.size();// 后缀数组:// sufGCD[i] 表示从索引 i 到末尾所有元素的 GCD// sufLCM[i] 表示从索引 i 到末尾所有元素的 LCMvector<int> sufGCD(n + 1, 0); // 初始化为 0, 表示 GCDvector<long long> sufLCM(n + 1, 1); // 初始化为 1, 表示 LCM// 计算后缀 GCD 和后缀 LCMfor (int i = n - 1; i >= 0; i--) {sufGCD[i] = gcd(sufGCD[i + 1], nums[i]);sufLCM[i] = lcm(sufLCM[i + 1], nums[i]);}// 初始答案: 不移除任何元素时的因子得分long long maxFactorScore = static_cast<long long>(sufGCD[0]) * sufLCM[0];// 前缀变量: preGCD 和 preLCMint preGCD = 0; // 前缀 GCD, 初始为 0long long preLCM = 1; // 前缀 LCM, 初始为 1// 枚举每个元素作为移除目标for (int i = 0; i < n; i++) {// 移除 nums[i] 后, 剩余部分的 GCD 和 LCMint remainingGCD = gcd(preGCD, sufGCD[i + 1]);long long remainingLCM = lcm(preLCM, sufLCM[i + 1]);// 更新最大因子得分maxFactorScore = max(maxFactorScore, static_cast<long long>(remainingGCD) * remainingLCM);// 更新前缀 GCD 和前缀 LCMpreGCD = gcd(preGCD, nums[i]);preLCM = lcm(preLCM, nums[i]);}return maxFactorScore;}
};
4、复杂度分析
-
时间复杂度:
-
后缀数组计算需要 O(n)。
-
遍历每个元素更新前缀和计算剩余数组的 GCD 和 LCM,也需要 O(n)。
-
总体复杂度为 O(n)。
-
-
空间复杂度:
- 使用了
sufGCD
和sufLCM
两个数组,空间复杂度为 O(n)。
- 使用了