Given an array a[] of n numbers, find the Least Common Multiple (LCM) of all the elements of the array. The LCM of an array is the smallest positive number that is divisible by every element of the array.
Examples:
Input: a[] = [1, 2, 8, 3]
Output: 24
Explanation: 24 is the smallest number divisible by 1, 2, 8 and 3.Input: a[] = [1, 8]
Output: 8
Explanation: 8 is the smallest number divisible by both 1 and 8.
Table of Content
[Naive Approach] Checking Multiples - O(max(a[i]) * n) Time and O(1) Space
The idea is to find LCM of two numbers by iterating through multiples of the larger number until we find one that is also divisible by the smaller number. We then extend this to the whole array by iteratively finding LCM of the current result with the next element.
Why can we compute LCM of an array one element at a time?
LCM satisfies the associative property:
LCM(a, b, c) = LCM(LCM(a, b), c)
Proof: A number x is divisible by a, b and c if and only if x is divisible by LCM(a, b) and c. The smallest such x is LCM(LCM(a, b), c). This extends to any number of elements: LCM(a₁, a₂, ... aₙ) = LCM(LCM(... LCM(LCM(a₁, a₂), a₃) ...), aₙ)
Example: arr = [1, 2, 8, 3]:
LCM(1, 2) = 2
LCM(2, 8) = 8
LCM(8, 3) = 24
#include <iostream>
#include <vector>
using namespace std;
int lcmOfTwo(int a, int b)
{
// Start from the larger number
int res = max(a, b);
// Keep incrementing by the larger number until divisible by both
while (res % a != 0 || res % b != 0)
res += max(a, b);
return res;
}
int lcmOfArray(vector<int> &a)
{
// Initialize res with first element
int res = a[0];
// Iteratively compute LCM of res with each element
for (int i = 1; i < (int)a.size(); i++)
res = lcmOfTwo(res, a[i]);
return res;
}
int main()
{
vector<int> a = {1, 2, 8, 3};
cout << lcmOfArray(a) << endl;
return 0;
}
class GFG {
static int lcmOfTwo(int a, int b) {
// Start from the larger number
int res = Math.max(a, b);
// Keep incrementing by the larger number until divisible by both
while (res % a != 0 || res % b != 0)
res += Math.max(a, b);
return res;
}
static int lcmOfArray(int[] a) {
// Initialize res with first element
int res = a[0];
// Iteratively compute LCM of res with each element
for (int i = 1; i < a.length; i++)
res = lcmOfTwo(res, a[i]);
return res;
}
public static void main(String[] args) {
int[] a = {1, 2, 8, 3};
System.out.println(lcmOfArray(a));
}
}
def lcmOfTwo(a, b):
# Start from the larger number
res = max(a, b)
# Keep incrementing by the larger number until divisible by both
while res % a != 0 or res % b != 0:
res += max(a, b)
return res
def lcmOfArray(a):
# Initialize res with first element
res = a[0]
# Iteratively compute LCM of res with each element
for i in range(1, len(a)):
res = lcmOfTwo(res, a[i])
return res
if __name__ == "__main__":
a = [1, 2, 8, 3]
print(lcmOfArray(a))
using System;
class GFG {
static int lcmOfTwo(int a, int b) {
// Start from the larger number
int res = Math.Max(a, b);
// Keep incrementing by the larger number until divisible by both
while (res % a != 0 || res % b != 0)
res += Math.Max(a, b);
return res;
}
static int lcmOfArray(int[] a) {
// Initialize res with first element
int res = a[0];
// Iteratively compute LCM of res with each element
for (int i = 1; i < a.Length; i++)
res = lcmOfTwo(res, a[i]);
return res;
}
static void Main() {
int[] a = {1, 2, 8, 3};
Console.WriteLine(lcmOfArray(a));
}
}
function lcmOfTwo(a, b) {
// Start from the larger number
let res = Math.max(a, b);
// Keep incrementing by the larger number until divisible by both
while (res % a !== 0 || res % b !== 0)
res += Math.max(a, b);
return res;
}
function lcmOfArray(a) {
// Initialize res with first element
let res = a[0];
// Iteratively compute LCM of res with each element
for (let i = 1; i < a.length; i++)
res = lcmOfTwo(res, a[i]);
return res;
}
// Driver code
let a = [1, 2, 8, 3];
console.log(lcmOfArray(a));
Output
24
[Expected Approach] Using GCD - O(n * log(max(a[i]))) Time and O(1) Space
The idea is to use the mathematical relation lcm(a, b) = (a / gcd(a, b)) * b to efficiently compute LCM of two numbers. We then extend this to the whole array by iteratively computing LCM of the current result with the next element using GCD.
Why does LCM(a, b) = (a × b) / GCD(a, b)?
Every number can be expressed as a product of prime factors. GCD(a, b) contains the common prime factors and LCM(a, b) contains the all prime factors of both.
Since GCD × LCM covers all prime factors of both numbers exactly once:
GCD(a, b) × LCM(a, b) = a × b
Therefore:
LCM(a, b) = (a × b) / GCD(a, b) = (a / GCD(a, b)) × b
Example: a=4, b=6:
4 = 22 , 6 = 2 × 3
GCD(4, 6) = 2 (common factors)
LCM(4, 6) = 22 × 3 = 12
Verify: (4 × 6) / 2 = 12
Note: We divide before multiplying (a / GCD) × b to avoid integer overflow.
#include <iostream>
#include <vector>
using namespace std;
int gcd(int a, int b)
{
// Euclidean algorithm to find GCD
while (b)
{
a = a % b;
swap(a, b);
}
return a;
}
int lcmOfArray(vector<int> &a)
{
// Initialize res with first element
int res = a[0];
// Iteratively compute LCM using gcd relation
for (int i = 1; i < (int)a.size(); i++)
res = (res / gcd(res, a[i])) * a[i];
return res;
}
int main()
{
vector<int> a = {1, 2, 8, 3};
cout << lcmOfArray(a) << endl;
return 0;
}
class GFG {
static int gcd(int a, int b) {
// Euclidean algorithm to find GCD
while (b != 0) {
int temp = b;
b = a % b;
a = temp;
}
return a;
}
static int lcmOfArray(int[] a) {
// Initialize res with first element
int res = a[0];
// Iteratively compute LCM using gcd relation
for (int i = 1; i < a.length; i++)
res = (res / gcd(res, a[i])) * a[i];
return res;
}
public static void main(String[] args) {
int[] a = {1, 2, 8, 3};
System.out.println(lcmOfArray(a));
}
}
def gcd(a, b):
# Euclidean algorithm to find GCD
while b:
a, b = b, a % b
return a
def lcmOfArray(a):
# Initialize res with first element
res = a[0]
# Iteratively compute LCM using gcd relation
for i in range(1, len(a)):
res = (res // gcd(res, a[i])) * a[i]
return res
if __name__ == "__main__":
a = [1, 2, 8, 3]
print(lcmOfArray(a))
using System;
class GFG {
static int gcd(int a, int b) {
// Euclidean algorithm to find GCD
while (b != 0) {
int temp = b;
b = a % b;
a = temp;
}
return a;
}
static int lcmOfArray(int[] a) {
// Initialize res with first element
int res = a[0];
// Iteratively compute LCM using gcd relation
for (int i = 1; i < a.Length; i++)
res = (res / gcd(res, a[i])) * a[i];
return res;
}
static void Main() {
int[] a = {1, 2, 8, 3};
Console.WriteLine(lcmOfArray(a));
}
}
function gcd(a, b) {
// Euclidean algorithm to find GCD
while (b) {
[a, b] = [b, a % b];
}
return a;
}
function lcmOfArray(a) {
// Initialize res with first element
let res = a[0];
// Iteratively compute LCM using gcd relation
for (let i = 1; i < a.length; i++)
res = (res / gcd(res, a[i])) * a[i];
return res;
}
// Driver code
let a = [1, 2, 8, 3];
console.log(lcmOfArray(a));
Output
24