Facebook Pixel

2654. Minimum Number of Operations to Make All Array Elements Equal to 1

MediumArrayMathNumber Theory
Leetcode Link

Problem Description

You have an array nums of positive integers (0-indexed). You can perform the following operation any number of times:

  • Choose any index i where 0 <= i < n - 1
  • Replace either nums[i] or nums[i+1] with their greatest common divisor (GCD)

Your goal is to make all elements in the array equal to 1 using the minimum number of operations. If it's impossible to achieve this, return -1.

For example, if you have two adjacent elements like [6, 10], you could replace either the 6 or the 10 with their GCD which is 2, giving you either [2, 10] or [6, 2].

The key insight is that you need to determine:

  1. Whether it's possible to reduce all elements to 1 (this is only possible if the GCD of all elements together equals 1)
  2. If possible, what's the minimum number of operations needed

The solution considers two main cases:

  • If there are already some 1s in the array, you can use each 1 to convert its neighbors to 1 through GCD operations (since GCD(1, any number) = 1)
  • If there are no 1s initially, you first need to create at least one 1 by finding the shortest subarray whose GCD equals 1, then spread that 1 to all other elements

The operation count depends on how many elements need to be changed and the minimum steps required to create the first 1 (if needed).

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

The first observation is that once we have a single 1 in the array, we can propagate it to all other elements. This is because GCD(1, x) = 1 for any positive integer x. So if we have a 1 at position i, we can make position i+1 equal to 1, then use that new 1 to convert position i+2, and so on. Similarly, we can propagate leftward.

If the array already contains some 1s, we don't need to create any. We just need to convert all non-1 elements to 1. Each non-1 element requires exactly one operation to become 1 (by taking GCD with an adjacent 1). So if we have cnt ones already, we need n - cnt operations.

The challenging case is when there are no 1s initially. We need to create at least one 1 first. To create a 1, we need to find two or more consecutive elements whose GCD equals 1. The key insight is that we want to find the shortest such subarray because:

  • Creating a 1 from a subarray of length k requires k - 1 operations (we repeatedly take GCD of adjacent pairs until we reduce the entire subarray to a single 1)
  • Once we have one 1, we need n - 1 more operations to propagate it to all other positions

Therefore, we search for the minimum length subarray whose GCD is 1. For each starting position i, we extend to position j and compute the GCD of elements from i to j. When this GCD becomes 1, we've found a candidate subarray of length j - i + 1.

If no such subarray exists (meaning the GCD of the entire array is greater than 1), it's impossible to make all elements equal to 1, so we return -1.

The total operations needed when starting with no 1s is: (minimum subarray length - 1) to create the first 1, plus (n - 1) to propagate it to all positions.

Learn more about Math patterns.

Solution Approach

The implementation follows a two-phase approach based on whether 1s already exist in the array:

Phase 1: Check for existing 1s

cnt = nums.count(1)
if cnt:
    return n - cnt

First, we count how many 1s are already in the array. If there are any 1s present, we can immediately return n - cnt since each non-1 element needs exactly one operation to become 1 through GCD with an adjacent 1.

Phase 2: Find minimum length subarray with GCD = 1

mi = n + 1
for i in range(n):
    g = 0
    for j in range(i, n):
        g = gcd(g, nums[j])
        if g == 1:
            mi = min(mi, j - i + 1)

If no 1s exist, we need to create one. We use a nested loop approach:

  • The outer loop iterates through each starting position i
  • For each starting position, we progressively extend the subarray by including elements at position j
  • We maintain a running GCD g of all elements in the current subarray [i, j]
  • The property GCD(a, GCD(b, c)) = GCD(GCD(a, b), c) allows us to update the GCD incrementally
  • When g becomes 1, we've found a valid subarray of length j - i + 1
  • We track the minimum length found in variable mi

Final calculation:

return -1 if mi > n else n - 1 + mi - 1
  • If mi > n, no valid subarray was found (impossible case), return -1
  • Otherwise, return n - 1 + mi - 1, which simplifies to n + mi - 2:
    • mi - 1 operations to create the first 1 from the minimum length subarray
    • n - 1 operations to propagate this 1 to all other positions

The algorithm has time complexity O(n² × log(max(nums))) where the log factor comes from the GCD computation, and space complexity O(1) as we only use a few variables.

Ready to land your dream job?

Unlock your dream job with a 5-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through the solution with the array nums = [6, 10, 15].

Step 1: Check for existing 1s

  • Count of 1s = 0
  • Since there are no 1s, we need to create one first

Step 2: Find minimum length subarray with GCD = 1

We'll check all possible subarrays:

Starting at index 0:

  • Subarray [6]: GCD = 6 (not 1)
  • Subarray [6, 10]: GCD(6, 10) = 2 (not 1)
  • Subarray [6, 10, 15]: GCD(GCD(6, 10), 15) = GCD(2, 15) = 1 ✓
    • Length = 3

Starting at index 1:

  • Subarray [10]: GCD = 10 (not 1)
  • Subarray [10, 15]: GCD(10, 15) = 5 (not 1)

Starting at index 2:

  • Subarray [15]: GCD = 15 (not 1)

Minimum subarray length found = 3

Step 3: Calculate total operations

To create the first 1 from the subarray [6, 10, 15]:

  • Operation 1: Replace 6 with GCD(6, 10) = 2 → [2, 10, 15]
  • Operation 2: Replace 2 with GCD(2, 15) = 1 → [1, 10, 15]
  • This took 3 - 1 = 2 operations

Now propagate the 1 to remaining elements:

  • Operation 3: Replace 10 with GCD(1, 10) = 1 → [1, 1, 15]
  • Operation 4: Replace 15 with GCD(1, 15) = 1 → [1, 1, 1]
  • This took 3 - 1 = 2 more operations

Total operations = (mi - 1) + (n - 1) = 2 + 2 = 4

Using the formula: n + mi - 2 = 3 + 3 - 2 = 4

Solution Implementation

1from typing import List
2from math import gcd
3
4class Solution:
5    def minOperations(self, nums: List[int]) -> int:
6        """
7        Find minimum operations to make all elements equal to 1.
8        Each operation: replace two adjacent elements with their GCD.
9        """
10        n = len(nums)
11      
12        # Count existing 1s in the array
13        ones_count = nums.count(1)
14      
15        # If there are already 1s, we need (n - ones_count) operations
16        # to convert all non-1 elements to 1
17        if ones_count > 0:
18            return n - ones_count
19      
20        # Find minimum length subarray with GCD = 1
21        min_length = n + 1
22      
23        for start_idx in range(n):
24            current_gcd = 0
25          
26            # Check all subarrays starting from start_idx
27            for end_idx in range(start_idx, n):
28                current_gcd = gcd(current_gcd, nums[end_idx])
29              
30                # If we found a subarray with GCD = 1
31                if current_gcd == 1:
32                    subarray_length = end_idx - start_idx + 1
33                    min_length = min(min_length, subarray_length)
34                    break  # No need to extend this subarray further
35      
36        # If no subarray has GCD = 1, it's impossible
37        if min_length > n:
38            return -1
39      
40        # Operations needed: (min_length - 1) to create first 1,
41        # then (n - 1) to propagate it to all positions
42        return n - 1 + min_length - 1
43
1class Solution {
2    /**
3     * Finds the minimum number of operations to make all elements in the array equal to 1.
4     * An operation consists of replacing an element with the GCD of two adjacent elements.
5     * 
6     * @param nums the input array
7     * @return minimum operations needed, or -1 if impossible
8     */
9    public int minOperations(int[] nums) {
10        int arrayLength = nums.length;
11      
12        // Count how many 1s already exist in the array
13        int onesCount = 0;
14        for (int num : nums) {
15            if (num == 1) {
16                onesCount++;
17            }
18        }
19      
20        // If there are already 1s in the array, we need (n - onesCount) operations
21        // to convert all non-1 elements to 1
22        if (onesCount > 0) {
23            return arrayLength - onesCount;
24        }
25      
26        // Find the minimum length subarray whose GCD equals 1
27        int minSubarrayLength = arrayLength + 1;
28      
29        // Try all possible subarrays starting from index i
30        for (int i = 0; i < arrayLength; i++) {
31            int currentGcd = 0;
32          
33            // Extend the subarray from i to j
34            for (int j = i; j < arrayLength; j++) {
35                // Calculate GCD of all elements from index i to j
36                currentGcd = gcd(currentGcd, nums[j]);
37              
38                // If we found a subarray with GCD = 1, update minimum length
39                if (currentGcd == 1) {
40                    minSubarrayLength = Math.min(minSubarrayLength, j - i + 1);
41                    break; // No need to extend further from this starting point
42                }
43            }
44        }
45      
46        // If no subarray with GCD = 1 exists, return -1
47        if (minSubarrayLength > arrayLength) {
48            return -1;
49        }
50      
51        // Total operations = (minSubarrayLength - 1) to create first 1 
52        // + (arrayLength - 1) to propagate 1 to all positions
53        return arrayLength - 1 + minSubarrayLength - 1;
54    }
55  
56    /**
57     * Calculates the Greatest Common Divisor (GCD) of two numbers using Euclidean algorithm.
58     * 
59     * @param a first number
60     * @param b second number
61     * @return GCD of a and b
62     */
63    private int gcd(int a, int b) {
64        return b == 0 ? a : gcd(b, a % b);
65    }
66}
67
1class Solution {
2public:
3    int minOperations(vector<int>& nums) {
4        int n = nums.size();
5      
6        // Count how many 1s already exist in the array
7        int onesCount = 0;
8        for (int num : nums) {
9            if (num == 1) {
10                ++onesCount;
11            }
12        }
13      
14        // If there are already 1s in the array, we need (n - onesCount) operations
15        // to convert all other elements to 1
16        if (onesCount > 0) {
17            return n - onesCount;
18        }
19      
20        // Find the minimum length subarray whose GCD is 1
21        int minLength = n + 1;
22        for (int i = 0; i < n; ++i) {
23            int currentGcd = 0;
24            for (int j = i; j < n; ++j) {
25                // Calculate GCD of subarray nums[i..j]
26                currentGcd = gcd(currentGcd, nums[j]);
27              
28                // If GCD becomes 1, update minimum length
29                if (currentGcd == 1) {
30                    minLength = min(minLength, j - i + 1);
31                    break;  // No need to extend this subarray further
32                }
33            }
34        }
35      
36        // If no subarray has GCD of 1, it's impossible to create any 1s
37        if (minLength > n) {
38            return -1;
39        }
40      
41        // Total operations: (minLength - 1) to create the first 1,
42        // then (n - 1) operations to convert all other elements to 1
43        return (minLength - 1) + (n - 1);
44    }
45};
46
1/**
2 * Calculates the minimum number of operations to make all elements in the array equal to 1
3 * An operation consists of replacing an element with the GCD of two adjacent elements
4 * @param nums - The input array of positive integers
5 * @returns The minimum number of operations, or -1 if impossible
6 */
7function minOperations(nums: number[]): number {
8    const arrayLength: number = nums.length;
9  
10    // Count how many 1s are already in the array
11    let onesCount: number = 0;
12    for (const num of nums) {
13        if (num === 1) {
14            onesCount++;
15        }
16    }
17  
18    // If there are already 1s in the array, we need (n - onesCount) operations
19    // to convert all other elements to 1
20    if (onesCount > 0) {
21        return arrayLength - onesCount;
22    }
23  
24    // Find the minimum length subarray whose GCD equals 1
25    let minSubarrayLength: number = arrayLength + 1;
26  
27    // Try all possible subarrays starting from index i
28    for (let startIndex: number = 0; startIndex < arrayLength; startIndex++) {
29        let currentGcd: number = 0;
30      
31        // Extend the subarray from startIndex to endIndex
32        for (let endIndex: number = startIndex; endIndex < arrayLength; endIndex++) {
33            // Calculate GCD of current subarray
34            currentGcd = gcd(currentGcd, nums[endIndex]);
35          
36            // If we found a subarray with GCD = 1, update minimum length
37            if (currentGcd === 1) {
38                minSubarrayLength = Math.min(minSubarrayLength, endIndex - startIndex + 1);
39            }
40        }
41    }
42  
43    // If no subarray has GCD = 1, it's impossible to make all elements 1
44    if (minSubarrayLength > arrayLength) {
45        return -1;
46    }
47  
48    // Total operations = (minSubarrayLength - 1) to create first 1 
49    // + (arrayLength - 1) to propagate 1 to all positions
50    return arrayLength - 1 + minSubarrayLength - 1;
51}
52
53/**
54 * Calculates the Greatest Common Divisor (GCD) of two numbers using Euclidean algorithm
55 * @param a - First number
56 * @param b - Second number
57 * @returns The GCD of a and b
58 */
59function gcd(a: number, b: number): number {
60    return b === 0 ? a : gcd(b, a % b);
61}
62

Time and Space Complexity

Time Complexity: O(n²)

The algorithm consists of several parts:

  • Counting 1s in the array takes O(n) time
  • If there are no 1s, we have nested loops:
    • Outer loop runs n times (from i = 0 to n-1)
    • Inner loop runs at most n-i times for each i
    • Inside the inner loop, gcd(g, nums[j]) operation takes O(log(max(nums))) time
    • Since we're looking for the minimum subarray with GCD = 1, in the worst case we examine all O(n²) subarrays

The total time complexity is O(n² × log(max(nums))). However, since the log factor is typically small compared to array operations and the problem constraints usually have bounded values, this is often simplified to O(n²).

Space Complexity: O(1)

The algorithm uses only a constant amount of extra space:

  • Variables n, cnt, mi, i, j, and g each take O(1) space
  • No additional data structures are created
  • The gcd function uses O(1) space (iterative implementation) or O(log(min(a,b))) space if recursive, but this doesn't affect the overall complexity

Therefore, the space complexity is O(1) excluding the input array.

Learn more about how to find time and space complexity quickly.

Common Pitfalls

1. Incorrect GCD Initialization

A common mistake is initializing the GCD variable incorrectly when computing the GCD of a subarray. Some might initialize it as current_gcd = nums[start_idx] instead of current_gcd = 0.

Why it's wrong: Starting with nums[start_idx] would skip including that element in the GCD calculation for the first iteration.

Correct approach: Initialize with 0 because GCD(0, x) = x for any positive integer x, which correctly includes the first element.

# Wrong
for start_idx in range(n):
    current_gcd = nums[start_idx]  # Incorrect initialization
    for end_idx in range(start_idx + 1, n):  # Skips single element check
        current_gcd = gcd(current_gcd, nums[end_idx])

# Correct
for start_idx in range(n):
    current_gcd = 0  # Correct initialization
    for end_idx in range(start_idx, n):
        current_gcd = gcd(current_gcd, nums[end_idx])

2. Forgetting to Check Single Element Arrays

When the array has only one element, the logic needs special handling. If n = 1 and nums[0] = 1, the answer is 0. If nums[0] ≠ 1, it's impossible (-1).

Solution: The provided code handles this correctly through the initial check for existing 1s and the impossibility check, but it's easy to overlook in custom implementations.

3. Incorrect Final Operation Count

A frequent error is miscalculating the total operations needed when no 1s exist initially.

Common mistakes:

  • Returning just min_length - 1 (forgetting to propagate the 1)
  • Returning n + min_length (off by one error)
  • Returning 2 * (n - 1) (assuming symmetric operations)

Correct formula: (min_length - 1) + (n - 1) where:

  • min_length - 1: operations to create the first 1 from the minimum subarray
  • n - 1: operations to propagate that 1 to all other positions

4. Breaking Too Early in Subarray Search

Some might break immediately after finding the first subarray with GCD = 1, missing potentially shorter subarrays.

# Wrong - stops at first valid subarray
for i in range(n):
    g = 0
    for j in range(i, n):
        g = gcd(g, nums[j])
        if g == 1:
            return n + (j - i + 1) - 2  # Wrong! Might not be minimum

# Correct - finds minimum length across all valid subarrays
min_length = n + 1
for i in range(n):
    g = 0
    for j in range(i, n):
        g = gcd(g, nums[j])
        if g == 1:
            min_length = min(min_length, j - i + 1)
            break  # Can break here since extending won't give shorter subarray

5. Not Handling the Impossible Case

Forgetting that if the GCD of the entire array is greater than 1, it's impossible to make all elements equal to 1.

Example: For array [2, 4, 6, 8], the GCD of all elements is 2, so no sequence of operations can produce a 1.

Solution: The check if min_length > n: return -1 handles this case, as no valid subarray will be found if the overall GCD > 1.

Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

In a binary min heap, the maximum element can be found in:


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More