Find the Maximum Factor Score of Array
MEDIUMDescription
You are given an integer array nums.
The factor score of an array is defined as the product of the LCM and GCD of all elements of that array.
Return the maximum factor score of nums after removing at most one element from it.
Note that both the LCM and GCD of a single number are the number itself, and the factor score of an empty array is 0.
Example 1:
Input: nums = [2,4,8,16]
Output: 64
Explanation:
On removing 2, the GCD of the rest of the elements is 4 while the LCM is 16, which gives a maximum factor score of 4 * 16 = 64.
Example 2:
Input: nums = [1,2,3,4,5]
Output: 60
Explanation:
The maximum factor score of 60 can be obtained without removing any elements.
Example 3:
Input: nums = [3]
Output: 9
Constraints:
1 <= nums.length <= 1001 <= nums[i] <= 30
Approaches
Checkout 2 different approaches to solve Find the Maximum Factor Score of Array. Click on different approaches to view the approach and algorithm in detail.
Optimized Approach using Prefix and Suffix Arrays
This approach improves upon the brute-force method by avoiding redundant computations. The key idea is to precompute the GCD and LCM of all prefixes and suffixes of the array. With these precomputed values, we can find the GCD and LCM of any subarray (formed by removing one element) in constant time (plus the time for a single GCD/LCM operation).
Algorithm
- Handle the edge case where
n=1. The score isnums[0] * nums[0]. - Create four arrays of size
nto store prefix/suffix GCDs and LCMs:prefixGcd,suffixGcd,prefixLcm,suffixLcm. Uselongtype for LCM arrays to prevent overflow. - Calculate all prefix GCDs and LCMs.
prefixGcd[i]is the GCD ofnums[0...i].prefixLcm[i]is the LCM ofnums[0...i]. This takes a single pass from left to right. - Calculate all suffix GCDs and LCMs.
suffixGcd[i]is the GCD ofnums[i...n-1].suffixLcm[i]is the LCM ofnums[i...n-1]. This takes a single pass from right to left. - Calculate the factor score for the original array (no removals) using
prefixGcd[n-1]andprefixLcm[n-1]. InitializemaxScorewith this value. - Iterate with an index
ifrom0ton-1to simulate removingnums[i]. - For each
i, determine the GCD and LCM of the remaining elements using the precomputed arrays.- If
iis the first element, the new GCD/LCM aresuffixGcd[1]andsuffixLcm[1]. - If
iis the last element, they areprefixGcd[n-2]andprefixLcm[n-2]. - Otherwise, they are
gcd(prefixGcd[i-1], suffixGcd[i+1])andlcm(prefixLcm[i-1], suffixLcm[i+1]).
- If
- Calculate the factor score for this configuration and update
maxScoreif it's larger. - After the loop, cast the final
maxScoretointand return it.
When an element nums[i] is removed, the remaining elements form two contiguous blocks: nums[0...i-1] and nums[i+1...n-1]. The GCD of the new subarray is GCD(GCD of nums[0...i-1], GCD of nums[i+1...n-1]). A similar property holds for the LCM.
This observation allows us to use precomputation. We create four arrays:
prefixGcd[i]: GCD ofnums[0]throughnums[i].suffixGcd[i]: GCD ofnums[i]throughnums[n-1].prefixLcm[i]: LCM ofnums[0]throughnums[i].suffixLcm[i]: LCM ofnums[i]throughnums[n-1].
These arrays can be populated in O(N * log(M)) time. For example, prefixGcd[i] = gcd(prefixGcd[i-1], nums[i]).
After precomputation, we first calculate the score for the full array (suffixGcd[0] * suffixLcm[0]). Then, we iterate from i = 0 to n-1 to consider removing nums[i]. For each i, the GCD and LCM of the remaining elements are found by combining the corresponding prefix and suffix values in O(log(M)) time. This significantly speeds up the process compared to re-calculating from scratch each time.
class Solution {
private long gcd(long a, long b) {
while (b != 0) {
long temp = b;
b = a % b;
a = temp;
}
return a;
}
private long lcm(long a, long b) {
if (a == 0 || b == 0) return 0;
if (a == 1) return b;
if (b == 1) return a;
return (a / gcd(a, b)) * b; // Divide first to prevent overflow
}
public int maxFactorScore(int[] nums) {
int n = nums.length;
if (n == 1) {
long val = nums[0];
return (int) (val * val);
}
long[] prefixGcd = new long[n];
long[] suffixGcd = new long[n];
long[] prefixLcm = new long[n];
long[] suffixLcm = new long[n];
// Populate prefix arrays
prefixGcd[0] = nums[0];
prefixLcm[0] = nums[0];
for (int i = 1; i < n; i++) {
prefixGcd[i] = gcd(prefixGcd[i - 1], nums[i]);
prefixLcm[i] = lcm(prefixLcm[i - 1], nums[i]);
}
// Populate suffix arrays
suffixGcd[n - 1] = nums[n - 1];
suffixLcm[n - 1] = nums[n - 1];
for (int i = n - 2; i >= 0; i--) {
suffixGcd[i] = gcd(suffixGcd[i + 1], nums[i]);
suffixLcm[i] = lcm(suffixLcm[i + 1], nums[i]);
}
// Case 1: No removal
long maxScore = prefixGcd[n - 1] * prefixLcm[n - 1];
// Case 2: One element removed
for (int i = 0; i < n; i++) {
long currentGcd, currentLcm;
if (i == 0) { // Remove first element
currentGcd = suffixGcd[1];
currentLcm = suffixLcm[1];
} else if (i == n - 1) { // Remove last element
currentGcd = prefixGcd[n - 2];
currentLcm = prefixLcm[n - 2];
} else { // Remove middle element
currentGcd = gcd(prefixGcd[i - 1], suffixGcd[i + 1]);
currentLcm = lcm(prefixLcm[i - 1], suffixLcm[i + 1]);
}
maxScore = Math.max(maxScore, currentGcd * currentLcm);
}
return (int) maxScore;
}
}
Complexity Analysis
Pros and Cons
- Significantly more efficient than the brute-force approach.
- Reduces the overall time complexity from quadratic to linearithmic.
- Requires extra space proportional to the input size to store the prefix and suffix arrays.
- The implementation is slightly more complex than the brute-force approach.
Code Solutions
Checking out 3 solutions in different languages for Find the Maximum Factor Score of Array. Click on different languages to view the code.
class Solution {
public
long maxScore(int[] nums) {
int n = nums.length;
long[] sufGcd = new long[n + 1];
long[] sufLcm = new long[n + 1];
sufLcm[n] = 1;
for (int i = n - 1; i >= 0; --i) {
sufGcd[i] = gcd(sufGcd[i + 1], nums[i]);
sufLcm[i] = lcm(sufLcm[i + 1], nums[i]);
}
long ans = sufGcd[0] * sufLcm[0];
long preGcd = 0, preLcm = 1;
for (int i = 0; i < n; ++i) {
ans = Math.max(ans,
gcd(preGcd, sufGcd[i + 1]) * lcm(preLcm, sufLcm[i + 1]));
preGcd = gcd(preGcd, nums[i]);
preLcm = lcm(preLcm, nums[i]);
}
return ans;
}
private
long gcd(long a, long b) { return b == 0 ? a : gcd(b, a % b); }
private
long lcm(long a, long b) { return a / gcd(a, b) * b; }
}
Video Solution
Watch the video walkthrough for Find the Maximum Factor Score of Array
Similar Questions
5 related questions you might find useful
Patterns:
Data Structures:
Companies:
Subscribe to Scale Engineer newsletter
Learn about System Design, Software Engineering, and interview experiences every week.
No spam, unsubscribe at any time.