|
| 1 | +# [Problem 2654: Minimum Number of Operations to Make All Array Elements Equal to 1](https://leetcode.com/problems/minimum-number-of-operations-to-make-all-array-elements-equal-to-1/description/?envType=daily-question) |
| 2 | + |
| 3 | +## Initial thoughts (stream-of-consciousness) |
| 4 | +If any element is already 1, we can use it to make neighbors 1 by taking gcd(1, x) = 1, so we can "spread" the 1 across the array. Each non-1 element needs one operation to become 1 when there's at least one 1, so I think answer = n - (# of ones) in that case. |
| 5 | + |
| 6 | +If there are no ones, we need to create a 1 first. Creating a 1 requires finding a contiguous subarray whose gcd is 1; reducing that subarray to a single 1 takes some operations. For a subarray of length L whose gcd is 1, I recall it takes L-1 operations to produce a 1 inside it (by repeatedly taking gcd of adjacent elements). Once we have a single 1, we then need to spread it to the remaining n-1 elements, which costs n-1 operations. So total would be (L-1) + (n-1) = n + L - 2. If no subarray has gcd 1, it's impossible. |
| 7 | + |
| 8 | +So algorithm: count ones -> if any, return n - count_ones. Otherwise, find minimal L such that gcd of subarray = 1 (O(n^2) with gcd updates). If none -> -1. Else return n + L - 2. |
| 9 | + |
| 10 | +## Refining the problem, round 2 thoughts |
| 11 | +- Edge cases: |
| 12 | + - Already contains multiple 1s -> formula n - count_ones still holds. |
| 13 | + - Entire array gcd > 1 -> impossible. |
| 14 | + - n up to 50, so O(n^2 logA) (gcd updates) is fine. |
| 15 | +- Implementation detail: while scanning subarrays, if running gcd becomes 1 we can break the inner loop for that start index because extending only increases length. |
| 16 | +- Complexity: We'll compute gcd pairwise cumulatively to avoid recomputing from scratch; use math.gcd. |
| 17 | +- No tricky memory requirements. |
| 18 | + |
| 19 | +## Attempted solution(s) |
| 20 | +```python |
| 21 | +from math import gcd |
| 22 | +from typing import List |
| 23 | + |
| 24 | +class Solution: |
| 25 | + def minOperations(self, nums: List[int]) -> int: |
| 26 | + n = len(nums) |
| 27 | + # Count existing ones |
| 28 | + ones = sum(1 for x in nums if x == 1) |
| 29 | + if ones > 0: |
| 30 | + return n - ones |
| 31 | + |
| 32 | + # Find minimal subarray length with gcd == 1 |
| 33 | + min_len = float('inf') |
| 34 | + for i in range(n): |
| 35 | + g = nums[i] |
| 36 | + if g == 1: |
| 37 | + min_len = 1 |
| 38 | + break |
| 39 | + for j in range(i + 1, n): |
| 40 | + g = gcd(g, nums[j]) |
| 41 | + if g == 1: |
| 42 | + min_len = min(min_len, j - i + 1) |
| 43 | + break # no need to extend this start further |
| 44 | + |
| 45 | + if min_len == float('inf'): |
| 46 | + return -1 |
| 47 | + |
| 48 | + # To create the first 1 takes (min_len - 1) operations, |
| 49 | + # then spreading that 1 to the remaining n-1 elements takes (n - 1) operations. |
| 50 | + return (min_len - 1) + (n - 1) |
| 51 | +``` |
| 52 | +- Notes on approach: |
| 53 | + - If there is at least one 1 in nums, we need exactly one operation per non-1 to convert it to 1 using adjacent gcd with a 1, so answer = n - count_ones. |
| 54 | + - If no 1 exists, find the shortest contiguous segment whose gcd is 1 (length L). It takes L-1 operations to reduce that segment to a single 1, then n-1 operations to propagate that 1 to all elements. Total = n + L - 2. |
| 55 | +- Time complexity: O(n^2 * logA) where n = len(nums) (<=50) and logA is cost of gcd on values up to 1e6. Practically O(n^2). |
| 56 | +- Space complexity: O(1) extra space. |
0 commit comments