Replace Non-Coprime Numbers in Array

hard stack math number theory

Problem

You are given an array of integers nums. Repeatedly scan for any two adjacent values that are non-coprime (their greatest common divisor is greater than 1) and replace that pair with a single number equal to their least common multiple (LCM). Keep doing this until no adjacent pair shares a common factor. The final array is unique no matter which order the merges happen in. Return that array.

Inputnums = [6, 4, 3, 2, 7, 6, 2]
Output[12, 7, 6]
6, 4, 3, 2 all chain together via common factors and collapse into lcm = 12. 7 is coprime with both neighbours. The trailing 6 and 2 merge into lcm = 6.

from math import gcd

def replace_non_coprimes(nums):
    stack = []
    for x in nums:
        while stack:
            g = gcd(stack[-1], x)
            if g == 1:
                break
            x = stack.pop() // g * x
        stack.append(x)
    return stack
function gcd(a, b) {
  while (b) { [a, b] = [b, a % b]; }
  return a;
}
function replaceNonCoprimes(nums) {
  const stack = [];
  for (let x of nums) {
    while (stack.length) {
      const g = gcd(stack[stack.length - 1], x);
      if (g === 1) break;
      x = stack.pop() / g * x;
    }
    stack.push(x);
  }
  return stack;
}
class Solution {
    private long gcd(long a, long b) {
        while (b != 0) { long t = a % b; a = b; b = t; }
        return a;
    }
    public List<Integer> replaceNonCoprimes(int[] nums) {
        Deque<Long> stack = new ArrayDeque<>();
        for (int v : nums) {
            long x = v;
            while (!stack.isEmpty()) {
                long g = gcd(stack.peek(), x);
                if (g == 1) break;
                x = stack.pop() / g * x;
            }
            stack.push(x);
        }
        List<Integer> res = new ArrayList<>();
        for (long v : stack) res.add(0, (int) v);
        return res;
    }
}
long long gcdll(long long a, long long b) {
    while (b) { long long t = a % b; a = b; b = t; }
    return a;
}
vector<int> replaceNonCoprimes(vector<int>& nums) {
    vector<long long> stack;
    for (int v : nums) {
        long long x = v;
        while (!stack.empty()) {
            long long g = gcdll(stack.back(), x);
            if (g == 1) break;
            x = stack.back() / g * x;
            stack.pop_back();
        }
        stack.push_back(x);
    }
    return vector<int>(stack.begin(), stack.end());
}
Time: O(n log m) Space: O(n)