2197. Replace Non Coprime Numbers in Array
Problem Description
Given an array A
of positive integers, the task is to replace the adjacent non-coprime numbers with their Least Common Multiple (LCM), until it's not possible to do any more merges. A pair of numbers (a, b)
are called non-coprime if their Greatest Common Divisor (GCD) is greater than 1. The final array should be as short as possible.
Example:
Input: nums = [4, 6, 7, 30]
Output: [4, 6, 7, 30]
Explanation:
- The first pair of numbers (4, 6) have GCD of 2, so they are non-coprime. Replace them with their LCM, which is 12.
- The resulting array is [12, 7, 30]. There are no more adjacent non-coprime numbers, so the array is final.
Approach
- Initialize two pointers,
i
as a read pointer, andj
as a write pointer, both starting from the first element of the input arraynums
. - Iterate over the array with the read pointer
i
. For each numbernum
at positioni
, try to merge it with the previous numberans[j-1]
, as long as they are non-coprime. The merging is done by calculating the LCM ofans[j-1]
andnum
, replacingans[j-1]
with the LCM, and popping the last element ofans
. - Push the merged number or the original number to the back of
ans
. - Repeat steps 2-3 for all elements in the input array.
- Return the resulting array
ans
as the output.
Time Complexity
The time complexity of the algorithm is O(NlogM), where N is the number of elements in the input array, and M is the maximum number in the input array. This is because the time complexity of calculating GCD(a, b) is log(min(a, b)).
Example Walkthrough
Let's walk through the provided example:
Input: nums = [4, 6, 7, 30]
- Initialize read pointer
i
and write pointerj
- Iterate over the input array with the read pointer
i
i
= 0, num = 4, push 4 toans
: ans = [4]i
= 1, num = 6, GCD(4, 6) > 1, so merge 4 and 6 by calculating LCM(4, 6) = 12, ans = [12]i
= 2, num = 7, GCD(12, 7) = 1, push 7 toans
: ans = [12, 7]i
= 3, num = 30, GCD(7, 30) = 1, push 30 toans
: ans = [12, 7, 30]
- The final array is [12, 7, 30], which is our output.
Python Solution
python from math import gcd class Solution: def replaceNonCoprimes(self, nums): ans = [] for num in nums: while ans and gcd(ans[-1], num) > 1: num = (ans[-1] * num) // gcd(ans[-1], num) ans.pop() ans.append(num) return ans
Java Solution
java
import java.util.ArrayList;
import java.util.List;
class Solution {
public List<Integer> replaceNonCoprimes(int[] nums) {
List<Integer> ans = new ArrayList<>();
for (int num : nums) {
while (!ans.isEmpty() && gcd(ans.get(ans.size() - 1), num) > 1) {
num = lcm(ans.get(ans.size() - 1), num);
ans.remove(ans.size() - 1);
}
ans.add(num);
}
return ans;
}
private int gcd(int a, int b) {
if (b == 0) {
return a;
} else {
return gcd(b, a % b);
}
}
private int lcm(int a, int b) {
return a * b / gcd(a, b);
}
}
JavaScript Solution
javascript
class Solution {
replaceNonCoprimes(nums) {
const ans = [];
for (const num of nums) {
while (ans.length > 0 && this.gcd(ans[ans.length - 1], num) > 1) {
const temp = ans.pop();
ans.push(this.lcm(temp, num));
}
ans.push(num);
}
return ans;
}
gcd(a, b) {
if (b === 0) {
return a;
} else {
return this.gcd(b, a % b);
}
}
lcm(a, b) {
return a * b / this.gcd(a, b);
}
}
C++ Solution
cpp
#include <algorithm>
#include <vector>
class Solution {
public:
std::vector<int> replaceNonCoprimes(std::vector<int>& nums) {
std::vector<int> ans;
for (int num : nums) {
while (!ans.empty() && std::gcd(ans.back(), num) > 1) {
num = std::lcm(ans.back(), num);
ans.pop_back();
}
ans.push_back(num);
}
return ans;
}
};
C# Solution
csharp
using System;
using System.Collections.Generic;
public class Solution {
public IList<int> ReplaceNonCoprimes(int[] nums) {
List<int> ans = new List<int>();
foreach (int num in nums) {
while (ans.Count > 0 && Gcd(ans[ans.Count - 1], num) > 1) {
num = Lcm(ans[ans.Count - 1], num);
ans.RemoveAt(ans.Count - 1);
}
ans.Add(num);
}
return ans;
}
private int Gcd(int a, int b) {
if (b == 0) {
return a;
} else {
return Gcd(b, a % b);
}
}
private int Lcm(int a, int b) {
return a * b / Gcd(a, b);
}
}
Now that we have provided the solutions for Python, Java, JavaScript, C++, and C#, the article is deemed complete. The approach is explained in detail, which allows the reader to understand the problem and its solution. The solutions in different programming languages cover the most widely used languages, ensuring that almost every reader will find a solution in a language they are more comfortable with.
Ready to land your dream job?
Unlock your dream job with a 2-minute evaluator for a personalized learning plan!
Start EvaluatorWhat's the output of running the following function using input [30, 20, 10, 100, 33, 12]
?
1def fun(arr: List[int]) -> List[int]:
2 import heapq
3 heapq.heapify(arr)
4 res = []
5 for i in range(3):
6 res.append(heapq.heappop(arr))
7 return res
8
1public static int[] fun(int[] arr) {
2 int[] res = new int[3];
3 PriorityQueue<Integer> heap = new PriorityQueue<>();
4 for (int i = 0; i < arr.length; i++) {
5 heap.add(arr[i]);
6 }
7 for (int i = 0; i < 3; i++) {
8 res[i] = heap.poll();
9 }
10 return res;
11}
12
1class HeapItem {
2 constructor(item, priority = item) {
3 this.item = item;
4 this.priority = priority;
5 }
6}
7
8class MinHeap {
9 constructor() {
10 this.heap = [];
11 }
12
13 push(node) {
14 // insert the new node at the end of the heap array
15 this.heap.push(node);
16 // find the correct position for the new node
17 this.bubble_up();
18 }
19
20 bubble_up() {
21 let index = this.heap.length - 1;
22
23 while (index > 0) {
24 const element = this.heap[index];
25 const parentIndex = Math.floor((index - 1) / 2);
26 const parent = this.heap[parentIndex];
27
28 if (parent.priority <= element.priority) break;
29 // if the parent is bigger than the child then swap the parent and child
30 this.heap[index] = parent;
31 this.heap[parentIndex] = element;
32 index = parentIndex;
33 }
34 }
35
36 pop() {
37 const min = this.heap[0];
38 this.heap[0] = this.heap[this.size() - 1];
39 this.heap.pop();
40 this.bubble_down();
41 return min;
42 }
43
44 bubble_down() {
45 let index = 0;
46 let min = index;
47 const n = this.heap.length;
48
49 while (index < n) {
50 const left = 2 * index + 1;
51 const right = left + 1;
52
53 if (left < n && this.heap[left].priority < this.heap[min].priority) {
54 min = left;
55 }
56 if (right < n && this.heap[right].priority < this.heap[min].priority) {
57 min = right;
58 }
59 if (min === index) break;
60 [this.heap[min], this.heap[index]] = [this.heap[index], this.heap[min]];
61 index = min;
62 }
63 }
64
65 peek() {
66 return this.heap[0];
67 }
68
69 size() {
70 return this.heap.length;
71 }
72}
73
74function fun(arr) {
75 const heap = new MinHeap();
76 for (const x of arr) {
77 heap.push(new HeapItem(x));
78 }
79 const res = [];
80 for (let i = 0; i < 3; i++) {
81 res.push(heap.pop().item);
82 }
83 return res;
84}
85
Recommended Readings
LeetCode Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way we
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https algomonster s3 us east 2 amazonaws com recursion jpg You first
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!