Given an array arr[] of size n, containing positive integers, find the maximum possible GCD among all pairs of elements in the array.
Examples:
Input: arr[] = [1, 2, 3, 4, 5]
Output: 2
Explanation: The pair (2, 4) has GCD 2, which is the maximum among all pairs.Input: arr[] = [2, 4, 8, 12]
Output: 4
Explanation: The pair (4, 8) or (4, 12) has GCD 4, which is the maximum possible among all pairs in the array.
Table of Content
[Naive Approach] Check Every Pair - O(n² * log(maxElement)) Time and O(1) Space
The simplest idea is to check the GCD of every possible pair in the array and keep track of the maximum GCD obtained.
#include <bits/stdc++.h>
using namespace std;
// Function to calculate GCD
int gcd(int a, int b) {
while (b != 0) {
int temp = b;
b = a % b;
a = temp;
}
return a;
}
// Function to find maximum GCD
int maxGCD(vector<int>& arr) {
int n = arr.size();
int maxGcd = 0;
// Check all pairs
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
// Find GCD of current pair
int currentGcd = gcd(arr[i], arr[j]);
// Update maximum GCD
maxGcd = max(maxGcd, currentGcd);
}
}
return maxGcd;
}
int main() {
vector<int> arr = {2, 4, 8, 12};
cout << maxGCD(arr);
return 0;
}
class GFG {
// Function to calculate GCD
static int gcd(int a, int b) {
while (b != 0) {
int temp = b;
b = a % b;
a = temp;
}
return a;
}
// Function to find maximum GCD
static int maxGCD(int[] arr) {
int n = arr.length;
int maxGcd = 0;
// Check all pairs
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
// Find GCD of current pair
int currentGcd = gcd(arr[i], arr[j]);
// Update maximum GCD
maxGcd = Math.max(maxGcd, currentGcd);
}
}
return maxGcd;
}
public static void main(String[] args) {
int[] arr = {2, 4, 8, 12};
System.out.println(maxGCD(arr));
}
}
# Function to calculate GCD
def gcd(a, b):
while b != 0:
temp = b
b = a % b
a = temp
return a
# Function to find maximum GCD
def maxGCD(arr):
n = len(arr)
maxGcd = 0
# Check all pairs
for i in range(n):
for j in range(i + 1, n):
# Find GCD of current pair
currentGcd = gcd(arr[i], arr[j])
# Update maximum GCD
maxGcd = max(maxGcd, currentGcd)
return maxGcd
if __name__ == "__main__":
arr = [2, 4, 8, 12]
print(maxGCD(arr))
using System;
class GFG {
// Function to calculate GCD
static int gcd(int a, int b) {
while (b != 0) {
int temp = b;
b = a % b;
a = temp;
}
return a;
}
// Function to find maximum GCD
static int maxGCD(int[] arr) {
int n = arr.Length;
int maxGcd = 0;
// Check all pairs
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
// Find GCD of current pair
int currentGcd = gcd(arr[i], arr[j]);
// Update maximum GCD
maxGcd = Math.Max(maxGcd, currentGcd);
}
}
return maxGcd;
}
static void Main() {
int[] arr = {2, 4, 8, 12};
Console.WriteLine(maxGCD(arr));
}
}
// Function to calculate GCD
function gcd(a, b) {
while (b !== 0) {
let temp = b;
b = a % b;
a = temp;
}
return a;
}
// Function to find maximum GCD
function maxGCD(arr) {
let n = arr.length;
let maxGcd = 0;
// Check all pairs
for (let i = 0; i < n; i++) {
for (let j = i + 1; j < n; j++) {
// Find GCD of current pair
let currentGcd = gcd(arr[i], arr[j]);
// Update maximum GCD
maxGcd = Math.max(maxGcd, currentGcd);
}
}
return maxGcd;
}
// Driver code
let arr = [2, 4, 8, 12];
console.log(maxGCD(arr));
Output
4
[Better Approach] Divisor Counting - O(n * sqrt(maxElement) ) Time and O(maxElement) Space
The idea is based on a simple observation that a number can be the GCD of a pair only if it divides them. So instead of checking all pairs, we focus on divisors of each element. For every number in the array, we find all its divisors and maintain a count array count[i], where count[i] stores how many array elements are divisible by i.
- Find the maximum element in the array.
- Create a count array count[] of size maxElement + 1, initialized with 0.
- Traverse array and for every element, find all its divisors from 1 to sqrt(element).
- If i divides the element, increase count[i] amd increase count[element / i] if it is different from i.
- After processing all elements, traverse the count[] array from largest to smallest.
- The first index i such that count[i] > 1 is the required answer.
Consider array: arr[] = [2, 4, 8, 12]
Maximum element: 12 -> create count[0...12] = 0.
Step 1: Find divisors and update count
- 2 -> 1, 2
- 4 -> 1, 2, 4
- 8 -> 1, 2, 4, 8
- 12 -> 1, 2, 3, 4, 6, 12
Step 2: Updated count values
- count[1] = 4
- count[2] = 4
- count[4] = 3
- count[8] = 1
- count[12] = 1
Step 3: Final count array
Index :1 2 3 4 5 6 7 8 9 10 11 12
Count :4 4 1 3 0 1 0 1 0 0 0 1
Step 4: Traverse from largest to smallest
- 12 -> count = 1
- 11 -> count = 0
- ...
- 4 -> count = 3
Since count[4] > 1, 4 divides at least two numbers. So, the maximum possible GCD is: 4
#include <bits/stdc++.h>
using namespace std;
// Function to find maximum GCD
int maxGCD(vector<int>& arr) {
int maxElement = 0;
// Find maximum element
for (int x : arr) {
maxElement = max(maxElement, x);
}
// Count array
vector<int> count(maxElement + 1, 0);
// Find divisors of every element
for (int x : arr) {
for (int i = 1; i * i <= x; i++) {
if (x % i == 0) {
// First divisor
count[i]++;
// Second divisor
if (i != x / i) {
count[x / i]++;
}
}
}
}
// Find maximum divisor
// present in at least two numbers
for (int i = maxElement; i >= 1; i--) {
if (count[i] > 1) {
return i;
}
}
return 1;
}
int main() {
vector<int> arr = {2, 4, 8, 12};
cout << maxGCD(arr);
return 0;
}
class GFG {
// Function to find maximum GCD
static int maxGCD(int[] arr) {
int maxElement = 0;
// Find maximum element
for (int x : arr) {
maxElement = Math.max(maxElement, x);
}
// Count array
int[] count = new int[maxElement + 1];
// Find divisors of every element
for (int x : arr) {
for (int i = 1; i * i <= x; i++) {
if (x % i == 0) {
// First divisor
count[i]++;
// Second divisor
if (i != x / i) {
count[x / i]++;
}
}
}
}
// Find maximum divisor
// present in at least two numbers
for (int i = maxElement; i >= 1; i--) {
if (count[i] > 1) {
return i;
}
}
return 1;
}
public static void main(String[] args) {
int[] arr = {2, 4, 8, 12};
System.out.println(maxGCD(arr));
}
}
# Function to find maximum GCD
def maxGCD(arr):
maxElement = 0
# Find maximum element
for x in arr:
maxElement = max(maxElement, x)
# Count array
count = [0] * (maxElement + 1)
# Find divisors of every element
for x in arr:
i = 1
while i * i <= x:
if x % i == 0:
# First divisor
count[i] += 1
# Second divisor
if i != x // i:
count[x // i] += 1
i += 1
# Find maximum divisor
# present in at least two numbers
for i in range(maxElement, 0, -1):
if count[i] > 1:
return i
return 1
if __name__ == "__main__":
arr = [2, 4, 8, 12]
print(maxGCD(arr))
using System;
class GFG {
// Function to find maximum GCD
static int maxGCD(int[] arr) {
int maxElement = 0;
// Find maximum element
foreach (int x in arr) {
maxElement = Math.Max(maxElement, x);
}
// Count array
int[] count = new int[maxElement + 1];
// Find divisors of every element
foreach (int x in arr) {
for (int i = 1; i * i <= x; i++) {
if (x % i == 0) {
// First divisor
count[i]++;
// Second divisor
if (i != x / i) {
count[x / i]++;
}
}
}
}
// Find maximum divisor
// present in at least two numbers
for (int i = maxElement; i >= 1; i--) {
if (count[i] > 1) {
return i;
}
}
return 1;
}
static void Main() {
int[] arr = {2, 4, 8, 12};
Console.WriteLine(maxGCD(arr));
}
}
// Function to find maximum GCD
function maxGCD(arr) {
let maxElement = 0;
// Find maximum element
for (let x of arr) {
maxElement = Math.max(maxElement, x);
}
// Count array
let count = new Array(maxElement + 1).fill(0);
// Find divisors of every element
for (let x of arr) {
for (let i = 1; i * i <= x; i++) {
if (x % i === 0) {
// First divisor
count[i]++;
// Second divisor
if (i !== Math.floor(x / i)) {
count[Math.floor(x / i)]++;
}
}
}
}
// Find maximum divisor
// present in at least two numbers
for (let i = maxElement; i >= 1; i--) {
if (count[i] > 1) {
return i;
}
}
return 1;
}
// Driver code
let arr = [2, 4, 8, 12];
console.log(maxGCD(arr));
Output
4
[Expected Approach] Sieve-based Counting - O( (maxElement) * log (maxElement) ) Time and O(maxElement) Space
The approach is based on a key observation: if a number g is the GCD of a pair, then both numbers must be divisible by g. So, instead of checking all pairs, we focus on possible GCD values. We first build a frequency array freq[], where freq[i] stores the count of occurrences of i in the array.
Now, we iterate over all possible values of g from the largest element down to 1 and check all multiples of g (i.e., g, 2g, 3g, ...) using the frequency array. If the total count of numbers divisible by g is at least 2, then g can be the GCD of some pair. Since we process values in decreasing order, the first valid g encountered is the maximum possible GCD.
- Find the maximum element in the array (maxElement).
- Create a frequency array freq[] of size maxElement + 1.
- Store frequency of each element in the array.
- Iterate g from maxElement down to 1.
- For each g, traverse all multiples of g.
- Keep adding freq[multiple] to a count.
- If count ≥ 2, return g as the answer.
Consider array: arr = [2, 4, 8, 12]
Step 1: Build Frequency Array
- freq[2] = 1
- freq[4] = 1
- freq[8] = 1
- freq[12] = 1
(All other values have frequency 0)
Step 2: Check from Largest to Smallest
- g = 12 -> only 12 -> count = 1
- g = 11 -> no multiples -> count = 0
- g = 10 -> no multiples -> count = 0
- g = 9 -> no multiples -> count = 0
- g = 8 -> only 8 -> count = 1
- g = 7 -> no multiples -> count = 0
- g = 6 -> only 12 -> count = 1
- g = 5 -> no multiples -> count = 0
- g = 4 -> 4, 8, 12 -> count = 3
Since g = 4 is the first value from the top having count ≥ 2, so Maximum GCD = 4
#include <bits/stdc++.h>
using namespace std;
int maxGCD(vector<int>& arr) {
// Find the maximum element in the array
int maxElement = 0;
for (int x : arr) {
maxElement = max(maxElement, x);
}
// Frequency array to store occurrence of each number
vector<int> freq(maxElement + 1, 0);
for (int x : arr) {
freq[x]++;
}
// Try all possible GCD values from largest to smallest
for (int g = maxElement; g >= 1; g--) {
int count = 0;
// Check all multiples of current g
for (int multiple = g; multiple <= maxElement; multiple += g) {
// Add frequency of current multiple
count += freq[multiple];
// If at least two numbers are divisible by g
if (count >= 2) {
return g;
}
}
}
return 1;
}
int main() {
vector<int> arr = {2, 4, 8, 12};
cout << maxGCD(arr) << endl;
return 0;
}
public class GFG {
public static int maxGCD(int[] arr) {
// Find the maximum element in the array
int maxElement = 0;
for (int x : arr) {
maxElement = Math.max(maxElement, x);
}
// Frequency array to store occurrence of each number
int[] freq = new int[maxElement + 1];
for (int x : arr) {
freq[x]++;
}
// Try all possible GCD values from largest to smallest
for (int g = maxElement; g >= 1; g--) {
int count = 0;
// Check all multiples of current g
for (int multiple = g; multiple <= maxElement; multiple += g) {
// Add frequency of current multiple
count += freq[multiple];
// If at least two numbers are divisible by g
if (count >= 2) {
return g;
}
}
}
return 1;
}
public static void main(String[] args) {
int[] arr = {2, 4, 8, 12};
System.out.println(maxGCD(arr));
}
}
def maxGCD(arr):
# Find the maximum element in the array
maxElement = max(arr)
# Frequency array to store occurrence of each number
freq = [0] * (maxElement + 1)
for x in arr:
freq[x] += 1
# Try all possible GCD values from largest to smallest
for g in range(maxElement, 0, -1):
count = 0
# Check all multiples of current g
for multiple in range(g, maxElement + 1, g):
# Add frequency of current multiple
count += freq[multiple]
# If at least two numbers are divisible by g
if count >= 2:
return g
return 1
if __name__ == "__main__":
arr = [2, 4, 8, 12]
print(maxGCD(arr))
using System;
class GFG
{
static int maxGCD (int[] arr)
{
// Find the maximum element in the array
int maxElement = 0;
foreach (int x in arr)
{
maxElement = Math.Max(maxElement, x);
}
// Frequency array to store occurrence of each number
int[] freq = new int[maxElement + 1];
foreach (int x in arr)
{
freq[x]++;
}
// Try all possible GCD values from largest to smallest
for (int g = maxElement; g >= 1; g--)
{
int count = 0;
// Check all multiples of current g
for (int multiple = g; multiple <= maxElement; multiple += g)
{
// Add frequency of current multiple
count += freq[multiple];
// If at least two numbers are divisible by g
if (count >= 2)
{
return g;
}
}
}
return 1;
}
static void Main()
{
int[] arr = { 2, 4, 8, 12 };
Console.WriteLine(maxGCD(arr));
}
}
function maxGCD(arr) {
// Find the maximum element in the array
let maxElement = 0;
for (let x of arr) {
maxElement = Math.max(maxElement, x);
}
// Frequency array to store occurrence of each number
let freq = new Array(maxElement + 1).fill(0);
for (let x of arr) {
freq[x]++;
}
// Try all possible GCD values from largest to smallest
for (let g = maxElement; g >= 1; g--) {
let count = 0;
// Check all multiples of current g
for (let multiple = g; multiple <= maxElement; multiple += g) {
// Add frequency of current multiple
count += freq[multiple];
// If at least two numbers are divisible by g
if (count >= 2) {
return g;
}
}
}
return 1;
}
// Driver code
let arr = [2, 4, 8, 12];
console.log(maxGCD(arr));
Output
4