Longest subsequence having maximum GCD between any pair of distinct elements

Given an array arr[] consisting of N positive integers, the task is to find the maximum length of subsequence from the given array such that the GCD of any two distinct integers of the subsequence is maximum.

Examples:

Input: arr[] = {5, 14, 15, 20, 1}
Output: 3
Explanation: Subsequence with maximum GCD of any pair of distinct integers is {5, 15, 20}.
The GCD between any pair of distinct elements in the above sequence is 5 and it is the maximum GCD in the array.

Input: arr[] = {1, 2, 8, 5, 6}
Output: 3
Explanation:< Subsequence with maximum GCD of any pair of distinct integers is {2, 8, 6}.
The GCD between any two distinct number in the above sequence is 2 and it is the maximum GCD in the array.

Naive Approach: The simplest approach is to use recursion and generate all possible subsequence of the given array recursively and find the maximum length among those subsequences. Below are the steps:



  • Create a function to find the pair in the array with maximum GCD(say maxGCD) using the idea of Sieve Of Eratosthenes.
  • Create another function to count the maximum length of the subsequence array where GCD between any two distinct elements is maximum:
    • Create an auxiliary array arr1[] that stores the array element in sorted order.
    • Initialize the two variables as [0, 0] and recursively generate all the subsequence and return the maximum length of the subsequence having GCD as maxGCD.
  • After the above steps, print the maximum length return by the above recursive calls.

 Below is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program for the above approach
#include<bits/stdc++.h>
using namespace std;
 
// Function to find GCD of pair with
// maximum GCD
int findMaxGCD(int arr[], int N)
{
     
    // Stores maximum element of arr[]
    int high = 0;
     
    // Find the maximum element
    for(int i = 0; i < N; i++)
    {
        high = max(high, arr[i]);
    }
 
    // Maintain a count array
    int count[high + 1] = {0};
     
    // Store the frequency of arr[]
    for(int i = 0; i < N; i++)
    {
        count[arr[i]] += 1;
    }
 
    // Stores the multiples of a number
    int counter = 0;
 
    // Iterate over the  range [MAX, 1]
    for(int i = high; i > 0; i--)
    {
        int j = i;
 
        // Iterate from current potential
        // GCD till it is less than MAX
        while (j <= high)
        {
             
            // A multiple found
            if (count[j] > 0)
                counter += count[j];
 
            // Increment potential GCD by
            // itself io check i, 2i, 3i...
            j += i;
 
            // If 2 multiples found max
            // GCD found
            if (counter == 2)
                return i;
        }
        counter = 0;
    }
}
     
// Function to find longest subsequence
// such that GCD of any two distinct
// integers is maximum
int maxlen(int i, int j, int arr[],
           int arr1[], int N, int maxgcd)
{
    int a = 1;
 
    // Base Cases
    if (i >= N or j >= N)
        return 0;
 
    // Comapare current GCD to the
    // maximum GCD
    if (__gcd(arr[i], arr1[j]) == maxgcd &&
              arr[i] != arr1[j])
    {
         
        // If true increment and
        // move the pointer
        a = max(a, 1 + maxlen(i, j + 1,
                              arr, arr1,
                              N, maxgcd));
        return a;
    }
     
    // Return max of either subsequences
    return max(maxlen(i + 1, j, arr,
                      arr1, N, maxgcd),
               maxlen(i, j + 1, arr,
                      arr1, N, maxgcd));
}
 
// Driver Code
int main()
{
    int arr[] = { 1, 2, 8, 5, 6 };
    int arr1[] = { 1, 2, 8, 5, 6 };
     
    // Sorted array
    int n = sizeof(arr) / sizeof(arr[0]);
     
    sort(arr, arr + n);
    sort(arr1, arr1 + n);
     
    // Function call to calculate GCD of
    // pair with maximum GCD
    int maxgcd = findMaxGCD(arr, n);
     
    // Print the result
    cout << maxlen(0, 0, arr,
                   arr1, n, maxgcd) + 1;
}
 
// This code is contributed by ipg2016107

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program for the
// above approach
import java.util.*;
 
class GFG{
     
// Recursive function to
// return gcd of a and b 
static int __gcd(int a,
                 int b) 
  return b == 0 ?
         a :__gcd(b, a % b);    
}
   
// Function to find GCD of
// pair with maximum GCD
static int findMaxGCD(int arr[],
                      int N)
{   
  // Stores maximum element
  // of arr[]
  int high = 0;
 
  // Find the maximum element
  for(int i = 0; i < N; i++)
  {
    high = Math.max(high,
                    arr[i]);
  }
 
  // Maintain a count array
  int []count = new int[high + 1];
 
  // Store the frequency of arr[]
  for(int i = 0; i < N; i++)
  {
    count[arr[i]] += 1;
  }
 
  // Stores the multiples of
  // a number
  int counter = 0;
 
  // Iterate over the  range
  // [MAX, 1]
  for(int i = high; i > 0; i--)
  {
    int j = i;
 
    // Iterate from current potential
    // GCD till it is less than MAX
    while (j <= high)
    {
      // A multiple found
      if (count[j] > 0)
        counter += count[j];
 
      // Increment potential GCD by
      // itself io check i, 2i, 3i...
      j += i;
 
      // If 2 multiples found max
      // GCD found
      if (counter == 2)
        return i;
    }
    counter = 0;
  }
  return 0;
}
 
// Function to find longest
// subsequence such that GCD
// of any two distinct integers
// is maximum
static int maxlen(int i, int j,
                  int arr[],
                  int arr1[],
                  int N, int maxgcd)
{
  int a = 1;
 
  // Base Cases
  if (i >= N || j >= N)
    return 0;
 
  // Comapare current GCD to
  // the maximum GCD
  if (__gcd(arr[i], arr1[j]) == maxgcd &&
      arr[i] != arr1[j])
  {
    // If true increment and
    // move the pointer
    a = Math.max(a, 1 + maxlen(i, j + 1,
                               arr, arr1,
                               N, maxgcd));
    return a;
  }
 
  // Return max of either subsequences
  return Math.max(maxlen(i + 1, j, arr,
                         arr1, N, maxgcd),
                  maxlen(i, j + 1, arr,
                         arr1, N, maxgcd));
}
 
// Driver Code
public static void main(String[] args)
{
  int arr[] = {1, 2, 8, 5, 6};
  int arr1[] = {1, 2, 8, 5, 6};
 
  // Sorted array
  int n = arr.length;
 
  Arrays.sort(arr);
 
  // Function call to calculate GCD of
  // pair with maximum GCD
  int maxgcd = findMaxGCD(arr, n);
 
  // Print the result
  System.out.print(maxlen(0, 0, arr,
                          arr1, n, maxgcd));
}
}
 
// This code is contributed by gauravrajput1

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 program for the above approach
import math
 
# Function to find GCD of pair with
# maximum GCD
def findMaxGCD(arr, N):
     
    # Stores maximum element of arr[]
    high = 0
     
    # Find the maximum element
    for i in range(0, N):
        high = max(high, arr[i])
 
    # Maintain a count array
    count = [0] * (high + 1)
     
    # Store the frequency of arr[]
    for i in range(0, N):
        count[arr[i]] += 1
 
    # Stores the multiples of a number
    counter = 0
 
    # Iterate over the  range [MAX, 1]
    for i in range(high, 0, -1):
        j = i
 
        # Iterate from current potential
        # GCD till it is less than MAX
        while (j <= high):
 
            # A multiple found
            if (count[j] > 0):
                counter += count[j]
 
            # Increment potential GCD by
            # itself io check i, 2i, 3i...
            j += i
 
            # If 2 multiples found max
            # GCD found
            if (counter == 2):
                return i
 
        counter = 0
 
# Function to find longest subsequence
# such that GCD of any two distinct
# integers is maximum
def maxlen(i, j):
    a = 0
 
    # Base Cases
    if i >= N or j >= N:
        return 0
 
    # Comapare current GCD to the
    # maximum GCD
    if math.gcd(arr[i], arr1[j]) == maxgcd and arr[i] != arr1[j]:
 
        # If true increment and
        # move the pointer
        a = max(a, 1 + maxlen(i, j + 1))
        return a
 
    # Return max of either subsequences
    return max(maxlen(i + 1, j), maxlen(i, j + 1))
 
 
# Drivers Code
arr = [1, 2, 8, 5, 6]
 
# Sorted array
arr1 = sorted(arr)
 
# Length of the array
N = len(arr)
 
# Function call to calculate GCD of
# pair with maximum GCD
maxgcd = findMaxGCD(arr, N)
 
# Print the result
print(maxlen(0, 0))

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# program for the
// above approach
using System;
 
class GFG{
     
// Recursive function to
// return gcd of a and b 
static int __gcd(int a, int b) 
{
  return b == 0 ?
         a :__gcd(b, a % b);    
}
   
// Function to find GCD of
// pair with maximum GCD
static int findMaxGCD(int []arr,
                      int N)
{   
   
  // Stores maximum element
  // of []arr
  int high = 0;
 
  // Find the maximum element
  for(int i = 0; i < N; i++)
  {
    high = Math.Max(high,
                    arr[i]);
  }
 
  // Maintain a count array
  int []count = new int[high + 1];
 
  // Store the frequency of []arr
  for(int i = 0; i < N; i++)
  {
    count[arr[i]] += 1;
  }
 
  // Stores the multiples of
  // a number
  int counter = 0;
 
  // Iterate over the  range
  // [MAX, 1]
  for(int i = high; i > 0; i--)
  {
    int j = i;
 
    // Iterate from current potential
    // GCD till it is less than MAX
    while (j <= high)
    {
       
      // A multiple found
      if (count[j] > 0)
        counter += count[j];
 
      // Increment potential GCD by
      // itself io check i, 2i, 3i...
      j += i;
 
      // If 2 multiples found max
      // GCD found
      if (counter == 2)
        return i;
    }
    counter = 0;
  }
  return 0;
}
 
// Function to find longest
// subsequence such that GCD
// of any two distinct integers
// is maximum
static int maxlen(int i, int j,
                  int []arr,
                  int []arr1,
                  int N, int maxgcd)
{
  int a = 1;
 
  // Base Cases
  if (i >= N || j >= N)
    return 0;
 
  // Comapare current GCD to
  // the maximum GCD
  if (__gcd(arr[i], arr1[j]) == maxgcd &&
                      arr[i] != arr1[j])
  {
     
    // If true increment and
    // move the pointer
    a = Math.Max(a, 1 + maxlen(i, j + 1,
                               arr, arr1,
                               N, maxgcd));
    return a;
  }
 
  // Return max of either subsequences
  return Math.Max(maxlen(i + 1, j, arr,
                         arr1, N, maxgcd),
                  maxlen(i, j + 1, arr,
                         arr1, N, maxgcd));
}
 
// Driver Code
public static void Main(String[] args)
{
  int []arr = { 1, 2, 8, 5, 6 };
  int []arr1 = { 1, 2, 8, 5, 6 };
 
  // Sorted array
  int n = arr.Length;
 
  Array.Sort(arr);
 
  // Function call to calculate GCD of
  // pair with maximum GCD
  int maxgcd = findMaxGCD(arr, n);
 
  // Print the result
  Console.Write(maxlen(0, 0, arr,
                       arr1, n, maxgcd));
}
}
 
// This code is contributed by Princi Singh

chevron_right


Output: 

3












 

Time Complexity: O(2N)
Auxiliary Space: O(N)

Efficient Approach: To optimize the above approach, the idea is to use Dynamic Programming as there are many overlapping subproblems in the above solution which are solved again and again. Therefore, the recomputation of the same subproblems can be avoided by either using Memoization or Tabulation. Use a dictionary to memorize the maximum length of the subsequence between two indexes and use those values in the next recursion calls. Below are the steps:

  1. Perform all the above-explained steps.
  2. Use a dictionary dp to store the maximum length of the subsequence between two indexes.
  3. While having the recursive call just check in the table dp[][] whether the value is previously computed or not. If found to be true then use this value. Otherwise, call the function for other index range.
  4. Print the maximum length of subsequence calculated after the above steps.

 Below is the implementation of the above approach:

Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python program for the above approach
import math
 
# Function to find GCD of pair with
# maximum GCD
def findMaxGCD(arr, N):
     
    # Stores maximum element of arr[]
    high = 0
     
    # Find the maximum element
    for i in range(0, N):
        high = max(high, arr[i])
 
    # Maintain a count array
    count = [0] * (high + 1)
     
    # Store the frequency of arr[]
    for i in range(0, N):
        count[arr[i]] += 1
 
    # Stores the multiples of a number
    counter = 0
 
    # Iterate over the  range [MAX, 1]
    for i in range(high, 0, -1):
        j = i
 
        # Iterate from current potential
        # GCD till it is less than MAX
        while (j <= high):
 
            # A multiple found
            if (count[j] > 0):
                counter += count[j]
 
            # Increment potential GCD by
            # itself io check i, 2i, 3i...
            j += i
 
            # If 2 multiples found max
            # GCD found
            if (counter == 2):
                return i
 
        counter = 0
 
# Function to find longest subsequence
# such that GCD of any two distinct
# integers is maximum
def maxlen(i, j):
   
    a = 0
     
    # Create the key
    key = (i, j)
 
    # Base Case
    if i >= N or j >= N:
        return 0
     
    # Check if the current state is
    # already calculated
    if key in dp:
        return dp[key]
       
    # Comapare current GCD to the
    # maximum GCD
    if math.gcd(arr[i], arr1[j]) == maxgcd and arr[i] != arr1[j]:
 
        # If true increment and
        # move the pointer
        dp[key] = 1 + maxlen(i, j + 1)
 
        return dp[key]
 
    # Return max of either subsequences
    return max(maxlen(i + 1, j), maxlen(i, j + 1))
 
 
# Drivers code
arr = [1, 2, 8, 5, 6]
 
# Empty dictionary
dp = dict()
 
# Sorted array
arr1 = sorted(arr)
 
# Length of the array
N = len(arr)
 
# Function Call
maxgcd = findMaxGCD(arr, N)
 
# Print the result
print(maxlen(0, 0))

chevron_right


Output: 

3












 

Time Complexity: O(N2)
Auxiliary Space: O(N)

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.




My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.