Skip to content
Related Articles

Related Articles

Improve Article

Maximum length subarray with LCM equal to product

  • Difficulty Level : Medium
  • Last Updated : 03 Jun, 2021
Geek Week

Given an arr[], the task is to find the maximum length of the sub-array such that the LCM of the sub-array is equal to the product of numbers in the sub-array. If no valid sub-array exists, then print -1

Note: The length of the sub-array must be ≥ 2.

Examples:  

Input: arr[] = { 6, 10, 21} 
Output:
The sub-array { 10, 21 } satisfies the condition.

Input: arr[] = { 2, 2, 4} 
Output: -1 
No sub-array satisfies the condition. Hence, the output is -1. 



Naive Approach: Run nested loops to check the condition for every possible sub-array of length ≥ 2. If the sub-array satisfies the condition, then update ans = max(ans, length(sub-array)). Print the ans in the end.

Below is the implementation of the above approach:  

C++




// C++ implementation of the above approach
#include <bits/stdc++.h>
using namespace std;
 
#define ll long long
 
// Function to calculate gcd(a, b)
int gcd(int a, int b)
{
    if (b == 0)
        return a;
    return gcd(b, a % b);
}
 
// Function to return max length of subarray
// that satisfies the condition
int maxLengthSubArray(const int* arr, int n)
{
    int maxLen = -1;
    for (int i = 0; i < n - 1; i++) {
        for (int j = i + 1; j < n; j++) {
            ll lcm = 1LL * arr[i];
            ll product = 1LL * arr[i];
 
            // Update LCM and product of the
            // sub-array
            for (int k = i + 1; k <= j; k++) {
                lcm = (((arr[k] * lcm)) /
                          (gcd(arr[k], lcm)));
                product = product * arr[k];
            }
 
            // If the current sub-array satisfies
            // the condition
            if (lcm == product) {
 
                // Choose the maximum
                maxLen = max(maxLen, j - i + 1);
            }
        }
    }
 
    return maxLen;
}
 
// Driver code
int main()
{
    int arr[] = { 6, 10, 21 };
    int n = sizeof(arr) / sizeof(arr[0]);
    cout << maxLengthSubArray(arr, n);
    return 0;
}

Java




// Java implementation of the above approach
import java.util.*;
 
class GFG
{
 
// Function to calculate gcd(a, b)
static int gcd(int a, int b)
{
    if (b == 0)
        return a;
    return gcd(b, a % b);
}
 
// Function to return max length of subarray
// that satisfies the condition
static int maxLengthSubArray(int arr[], int n)
{
    int maxLen = -1;
    for (int i = 0; i < n - 1; i++)
    {
        for (int j = i + 1; j < n; j++)
        {
            int lcm = 1 * arr[i];
            int product = 1 * arr[i];
 
            // Update LCM and product of the
            // sub-array
            for (int k = i + 1; k <= j; k++)
             
            {
                lcm = (((arr[k] * lcm)) /
                        (gcd(arr[k], lcm)));
                product = product * arr[k];
            }
 
            // If the current sub-array satisfies
            // the condition
            if (lcm == product)
            {
 
                // Choose the maximum
                maxLen = Math.max(maxLen, j - i + 1);
            }
        }
    }
    return maxLen;
}
 
// Driver code
public static void main(String args[])
{
    int arr[] = { 6, 10, 21 };
    int n = arr.length;
    System.out.println(maxLengthSubArray(arr, n));
}
}
 
// This code is contributed by
// Shashank_Sharma

Python3




# Python3 implementation of the
# above approach
 
# Function to calculate gcd(a, b)
def gcd(a, b):
    if (b == 0):
        return a
    return gcd(b, a % b)
 
# Function to return max length of
# subarray that satisfies the condition
def maxLengthSubArray(arr, n):
 
    maxLen = -1
    for i in range(n - 1):
        for j in range(n):
            lcm = arr[i]
            product = arr[i]
 
            # Update LCM and product of the
            # sub-array
            for k in range(i + 1, j + 1):
                lcm = (((arr[k] * lcm)) //
                    (gcd(arr[k], lcm)))
                product = product * arr[k]
             
            # If the current sub-array satisfies
            # the condition
            if (lcm == product):
 
                # Choose the maximum
                maxLen = max(maxLen, j - i + 1)
    return maxLen
 
# Driver code
arr = [6, 10, 21 ]
n = len(arr)
print(maxLengthSubArray(arr, n))
 
# This code is contributed by
# mohit kumar 29

C#




// C# implementation of the above approach
using System;
 
class GFG
{
 
// Function to calculate gcd(a, b)
static int gcd(int a, int b)
{
    if (b == 0)
        return a;
    return gcd(b, a % b);
}
 
// Function to return max length of subarray
// that satisfies the condition
static int maxLengthSubArray(int[] arr, int n)
{
    int maxLen = -1;
    for (int i = 0; i < n - 1; i++)
    {
        for (int j = i + 1; j < n; j++)
        {
            int lcm = 1 * arr[i];
            int product = 1 * arr[i];
 
            // Update LCM and product of the
            // sub-array
            for (int k = i + 1; k <= j; k++)
             
            {
                lcm = (((arr[k] * lcm)) /
                        (gcd(arr[k], lcm)));
                product = product * arr[k];
            }
 
            // If the current sub-array satisfies
            // the condition
            if (lcm == product)
            {
 
                // Choose the maximum
                maxLen = Math.Max(maxLen, j - i + 1);
            }
        }
    }
    return maxLen;
}
 
// Driver code
public static void Main()
{
    int[] arr = { 6, 10, 21 };
    int n = arr.Length;
    Console.Write(maxLengthSubArray(arr, n));
}
}
 
// This code is contributed by ita_c

PHP




<?php
// PHP implementation of the above approach
 
// Function to calculate gcd(a, b)
function gcd($a, $b)
{
    if ($b == 0)
        return $a;
    return gcd($b, $a % $b);
}
 
// Function to return max length of subarray
// that satisfies the condition
function maxLengthSubArray(&$arr, $n)
{
    $maxLen = -1;
    for ($i = 0; $i < $n - 1; $i++)
    {
        for ($j = $i + 1; $j < $n; $j++)
        {
            $lcm = $arr[$i];
            $product = $arr[$i];
 
            // Update LCM and product of the
            // sub-array
            for ($k = $i + 1; $k <= $j; $k++)
            {
                $lcm = ((($arr[$k] * $lcm)) /
                        (gcd($arr[$k], $lcm)));
                $product = $product * $arr[$k];
            }
 
            // If the current sub-array satisfies
            // the condition
            if ($lcm == $product)
            {
 
                // Choose the maximum
                $maxLen = max($maxLen, $j - $i + 1);
            }
        }
    }
 
    return $maxLen;
}
 
// Driver code
$arr = array(6, 10, 21 );
$n = sizeof($arr);
echo(maxLengthSubArray($arr, $n));
 
// This code is contributed by Shivi_Aggarwal
?>

Javascript




<script>
// Javascript implementation of the above approach
 
// Function to calculate gcd(a, b)
function  gcd(a,b)
{
    if (b == 0)
        return a;
    return gcd(b, a % b);
}
 
// Function to return max length of subarray
// that satisfies the condition
function maxLengthSubArray(arr,n)
{
    let maxLen = -1;
    for (let i = 0; i < n - 1; i++)
    {
        for (let j = i + 1; j < n; j++)
        {
            let lcm = 1 * arr[i];
            let product = 1 * arr[i];
  
            // Update LCM and product of the
            // sub-array
            for (let k = i + 1; k <= j; k++)
              
            {
                lcm = (((arr[k] * lcm)) /
                        (gcd(arr[k], lcm)));
                product = product * arr[k];
            }
  
            // If the current sub-array satisfies
            // the condition
            if (lcm == product)
            {
  
                // Choose the maximum
                maxLen = Math.max(maxLen, j - i + 1);
            }
        }
    }
    return maxLen;
}
 
// Driver code
let arr=[6, 10, 21 ];
let n = arr.length;
document.write(maxLengthSubArray(arr, n));
     
 
// This code is contributed by unknown2108
</script>
Output: 
2

 

Efficient Approach: A sub-array will have its LCM equal to its product when no two elements in the sub-array have any common factor. 

For example:  

arr[] = { 6, 10, 21 }
Prime factorization yields: 
arr[] = { 2 * 3, 2 * 5, 3 * 7 }
[6, 10] has 2 as a common factor. 
[6, 10, 21] has 2 as a common factor between 6 and 10. 
Sub-array [10, 21] has no common factor between any 2 elements. Therefore, answer = 2.  

Firstly, prime factorization of numbers is done to deal with factors. To calculate the sub-array in which no 2 elements have a common factor, we use the two-pointer technique. 

Two pointers run, both from the right and they represent the current sub-array. We add elements in the sub-array from the right. Now there are two scenarios:  

  1. An element is added in the current sub-array if it has no factor in common with the current elements in the sub-array. If a common factor is found, then starting from the left, elements are subsequently eliminated until no common factor is found with the newly added element.
  2. If there are no common factors between the newly added element and existing elements, then update ans = max(ans, length of sub-array)

Below is the implementation of the above approach:  

C++




// C++ implementation of the above approach
#include <bits/stdc++.h>
 
#define pb push_back
#define N 100005
#define MAX 1000002
#define mem(a, b) memset(a, b, sizeof(a))
 
using namespace std;
 
int prime[MAX];
 
// Stores array of primes for every element
vector<int> v[N];
 
// Stores the position of a prime in the subarray
// in two pointer technique
int f[MAX];
 
// Function to store smallest prime factor of numbers
void sieve()
{
    prime[0] = prime[1] = 1;
    for (int i = 2; i < MAX; i++) {
        if (!prime[i]) {
            for (int j = i * 2; j < MAX; j += i) {
                if (!prime[j])
                    prime[j] = i;
            }
        }
    }
 
    for (int i = 2; i < MAX; i++) {
 
        // If number is prime,
        // then smallest prime factor is the
        // number itself
        if (!prime[i])
            prime[i] = i;
    }
}
 
// Function to return maximum length of subarray
// with LCM = product
int maxLengthSubArray(int* arr, int n)
{
    // Initialize f with -1
    mem(f, -1);
 
    for (int i = 0; i < n; ++i) {
 
        // Prime factorization of numbers
        // Store primes in a vector for every element
        while (arr[i] > 1) {
            int p = prime[arr[i]];
            arr[i] /= p;
            v[i].pb(p);
        }
    }
 
    // Two pointers l and r
    // denoting left and right of subarray
    int l = 0, r = 1, ans = -1;
 
    // f is a mapping.
    // prime -> index in the current subarray
    // With the help of f,
    // we can detect whether a prime has
    // already occurred in the subarray
    for (int i : v[0]) {
        f[i] = 0;
    }
 
    while (l <= r && r < n) {
        int flag = 0;
 
        for (int i = 0; i < v[r].size(); i++) {
 
            // Map the prime to the index
            if (f[v[r][i]] == -1 || f[v[r][i]] == r) {
                f[v[r][i]] = r;
            }
 
            // If already occurred then,
            // start removing elements from the left
            else {
                flag = 1;
                break;
            }
        }
 
        // Remove elements if flag = 1
        if (flag) {
 
            // Nullify entries of element at index 'l'
            for (int i : v[l]) {
                f[i] = -1;
            }
 
            // Increment 'l'
            l++;
        }
        else {
 
            // Maximize the answer when
            // no common factor is found
            ans = max(ans, r - l + 1);
            r++;
        }
    }
 
    // One length subarray is discarded
    if (ans == 1)
        ans = -1;
 
    return ans;
}
 
// Driver code
int main()
{
    sieve();
    int arr[] = { 6, 10, 21 };
    int n = sizeof(arr) / sizeof(arr[0]);
    cout << maxLengthSubArray(arr, n);
    return 0;
}

Java




// Java implementation of the above approach
import java.io.*;
import java.util.*;
 
class GFG{
     
static int N = 100005;
static int MAX = 1000002;
static int[] prime = new int[MAX];
 
// Stores array of primes for every element
static ArrayList<
       ArrayList<Integer>> v = new ArrayList<
                                   ArrayList<Integer>>();
 
// Stores the position of a prime in the
// subarray in two pointer technique
static int[] f = new int[MAX];
 
// Function to store smallest prime
// factor of numbers
static void sieve()
{
    for(int i = 0; i < N; i++)
    {
        v.add(new ArrayList<Integer>());
    }
     
    prime[0] = prime[1] = 1;
     
    for(int i = 2; i < MAX; i++)
    {
        if (prime[i] == 0)
        {
            for(int j = i * 2; j < MAX; j += i)
            {
                if (prime[j] == 0)
                {
                    prime[j] = i;
                }
            }
        }
    }
     
    for(int i = 2; i < MAX; i++)
    {
         
        // If number is prime, then
        // smallest prime factor is
        // the number itself
        if (prime[i] == 0)
        {
            prime[i] = i;
        }
    }
}
 
// Function to return maximum length of
// subarray with LCM = product
static int maxLengthSubArray(int[] arr, int n)
{
     
    // Initialize f with -1
    Arrays.fill(f, -1);
     
    for(int i = 0; i < n; ++i)
    {
         
        // Prime factorization of numbers
        // Store primes in a vector for
        // every element
        while (arr[i] > 1)
        {
            int p = prime[arr[i]];
            arr[i] /= p;
            v.get(i).add(p);
        }
    }
     
    // Two pointers l and r denoting
    // left and right of subarray
    int l = 0, r = 1, ans = -1;
     
    // f is a mapping.
    // prime -> index in the current subarray
    // With the help of f,
    // we can detect whether a prime has
    // already occurred in the subarray
    for(int i : v.get(0))
    {
        f[i] = 0;
    }
     
    while (l <= r && r < n)
    {
        int flag = 0;
         
        for(int i = 0; i < v.get(r).size(); i++)
        {
             
            // Map the prime to the index
            if (f[v.get(r).get(i)] == -1  ||
                f[v.get(r).get(i)] == r)
            {
                f[v.get(r).get(i)] = r;
            }
             
            // If already occurred then,
            // start removing elements
            // from the left
            else
            {
                flag = 1;
                break;
            }
        }
         
        // Remove elements if flag = 1
        if (flag != 0)
        {
             
            // Nullify entries of element
            // at index 'l'
            for(int i : v.get(l))
            {
                f[i] = -1;
            }
             
            // Increment 'l'
            l++;
        }
        else
        {
             
            // Maximize the answer when
            // no common factor is found
            ans = Math.max(ans, r - l + 1);
            r++;
        }
         
    }
     
    // One length subarray is discarded
    if (ans == 1)
    {
        ans = -1;
    }
    return ans;
}
 
// Driver code
public static void main(String[] args)
{
    sieve();
    int arr[] = { 6, 10, 21 };
    int n = arr.length;
     
    System.out.println(maxLengthSubArray(arr, n));
}
}
 
// This code is contributed by avanitrachhadiya2155

Python3




# Python3 implementation of the above approach
 
N = 100005
MAX = 1000002
 
 
 
prime = [0 for i in range(MAX + 1)]
 
# Stores array of primes for every element
v = [[] for i in range(N)]
 
# Stores the position of a prime in the subarray
# in two pointer technique
f = [-1 for i in range(MAX)]
 
# Function to store smallest prime factor of numbers
def sieve():
 
    prime[0], prime[1] = 1, 1
 
    for i in range(2, MAX + 1):
        if (prime[i] == 0):
            for j in range(i * 2, MAX, i):
                if (prime[j] == 0):
                    prime[j] = i
 
 
    for i in range(2, MAX):
 
        # If number is prime,
        # then smallest prime factor is the
        # number itself
        if (prime[i] == 0):
            prime[i] = i
 
# Function to return maximum length of subarray
# with LCM = product
def maxLengthSubArray(arr, n):
     
    # Initialize f with -1
    for i in range(n):
        f[i] = -1
 
    for i in range(n):
 
        # Prime factorization of numbers
        # Store primes in a vector for every element
        while (arr[i] > 1):
            p = prime[arr[i]]
            arr[i] //= p
            v[i].append(p)
 
    # Two pointers l and r
    # denoting left and right of subarray
    l, r, ans = 0, 1, -1
 
    # f is a mapping.
    # prime -> index in the current subarray
    # With the help of f,
    # we can detect whether a prime has
    # already occurred in the subarray
    for i in v[0]:
        f[i] = 0
 
    while (l <= r and r < n):
        flag = 0
 
        for i in range(len(v[r])):
 
            # Map the prime to the index
            if (f[v[r][i]] == -1 or f[v[r][i]] == r):
                f[v[r][i]] = r
 
            # If already occurred then,
            # start removing elements from the left
            else:
                flag = 1
                break
 
        # Remove elements if flag = 1
        if (flag):
 
            # Nullify entries of element at index 'l'
            for i in v[l]:
                f[i] = -1
 
            # Increment 'l'
            l += 1
        else :
 
            # Maximize the answer when
            # no common factor is found
            ans = max(ans, r - l + 1)
            r += 1
 
 
    # One length subarray is discarded
    if (ans == 1):
        ans = -1
 
    return ans
 
# Driver code
sieve()
arr = [6, 10, 21]
n = len(arr)
print(maxLengthSubArray(arr, n))
 
# This code is contributed by mohit kumar

C#




// C# implementation of the above approach
using System;
using System.Collections.Generic;
class GFG
{
 
  static int N = 100005;
  static int MAX = 1000002;
  static int[] prime = new int[MAX];
 
  // Stores array of primes for every element
  static List<List<int>> v = new List<List<int>>();
 
  // Stores the position of a prime in the
  // subarray in two pointer technique
  static int[] f = new int[MAX];
 
  // Function to store smallest prime
  // factor of numbers
  static void sieve()
  {
    for(int i = 0; i < N; i++)
    {
      v.Add(new List<int>());
    }
 
    prime[0] = prime[1] = 1;
 
    for(int i = 2; i < MAX; i++)
    {
      if (prime[i] == 0)
      {
        for(int j = i * 2; j < MAX; j += i)
        {
          if (prime[j] == 0)
          {
            prime[j] = i;
          }
        }
      }
    }
 
    for(int i = 2; i < MAX; i++)
    {
 
      // If number is prime, then
      // smallest prime factor is
      // the number itself
      if (prime[i] == 0)
      {
        prime[i] = i;
      }
    }
  }
 
  // Function to return maximum length of
  // subarray with LCM = product
  static int maxLengthSubArray(int[] arr, int n)
  {
    // Initialize f with -1
    Array.Fill(f, -1);   
    for(int i = 0; i < n; ++i)
    {
 
      // Prime factorization of numbers
      // Store primes in a vector for
      // every element
      while (arr[i] > 1)
      {
        int p = prime[arr[i]];
        arr[i] /= p;
        v[i].Add(p);
      }
    }
 
    // Two pointers l and r denoting
    // left and right of subarray
    int l = 0, r = 1, ans = -1;
 
    // f is a mapping.
    // prime -> index in the current subarray
    // With the help of f,
    // we can detect whether a prime has
    // already occurred in the subarray
 
    foreach(int i in v[0])
    {
      f[i] = 0;
    }
 
    while (l <= r && r < n)
    {
      int flag = 0;        
      for(int i = 0; i < v[r].Count; i++)
      {
 
        // Map the prime to the index
        if (f[v[r][i]] == -1  ||
            f[v[r][i]] == r)
        {
          f[v[r][i]] = r;
        }
 
        // If already occurred then,
        // start removing elements
        // from the left
        else
        {
          flag = 1;
          break;
        }
      }
 
      // Remove elements if flag = 1
      if (flag != 0)
      {
 
        // Nullify entries of element
        // at index 'l'
        foreach(int i in v[l])
        {
          f[i] = -1;
        }
 
        // Increment 'l'
        l++;
      }
      else
      {
 
        // Maximize the answer when
        // no common factor is found
        ans = Math.Max(ans, r - l + 1);
        r++;
      }
 
    }
 
    // One length subarray is discarded
    if (ans == 1)
    {
      ans = -1;
    }
    return ans;
  }
 
  // Driver code
  static public void Main ()
  {
    sieve();
    int[] arr = { 6, 10, 21 };
    int n = arr.Length;
    Console.WriteLine(maxLengthSubArray(arr, n));
  }
}
// This code is contributed by rag2127

Javascript




<script>
// Javascript implementation of the above approach
 
let N = 100005;
let MAX = 1000002;
let prime = new Array(MAX);
for(let i=0;i<prime.length;i++)
{
    prime[i]=0;
}
// Stores array of primes for every element
let v = [];
 
// Stores the position of a prime in the
// subarray in two pointer technique
let  f = new Array(MAX);
 
// Function to store smallest prime
// factor of numbers
function sieve()
{
    for(let i = 0; i < N; i++)
    {
        v.push([]);
    }
      
    prime[0] = prime[1] = 1;
      
    for(let i = 2; i < MAX; i++)
    {
        if (prime[i] == 0)
        {
            for(let j = i * 2; j < MAX; j += i)
            {
                if (prime[j] == 0)
                {
                    prime[j] = i;
                }
            }
        }
    }
      
    for(let i = 2; i < MAX; i++)
    {
          
        // If number is prime, then
        // smallest prime factor is
        // the number itself
        if (prime[i] == 0)
        {
            prime[i] = i;
        }
    }
}
 
// Function to return maximum length of
// subarray with LCM = product
function maxLengthSubArray(arr,n)
{
     // Initialize f with -1
    for(let i=0;i<f.length;i++)
    {
        f[i]=-1;
    }
      
    for(let i = 0; i < n; ++i)
    {
          
        // Prime factorization of numbers
        // Store primes in a vector for
        // every element
        while (arr[i] > 1)
        {
            let p = prime[arr[i]];
            arr[i] /= p;
            v[i].push(p);
        }
    }
      
    // Two pointers l and r denoting
    // left and right of subarray
    let l = 0, r = 1, ans = -1;
      
    // f is a mapping.
    // prime -> index in the current subarray
    // With the help of f,
    // we can detect whether a prime has
    // already occurred in the subarray
    for(let i=0;i< v[0].length;i++)
    {
        f[v[0][i]] = 0;
    }
      
    while (l <= r && r < n)
    {
        let flag = 0;
          
        for(let i = 0; i < v[r].length; i++)
        {
              
            // Map the prime to the index
            if (f[v[r][i]] == -1  ||
                f[v[r][i]] == r)
            {
                f[v[r][i]] = r;
            }
              
            // If already occurred then,
            // start removing elements
            // from the left
            else
            {
                flag = 1;
                break;
            }
        }
          
        // Remove elements if flag = 1
        if (flag != 0)
        {
              
            // Nullify entries of element
            // at index 'l'
            for(let i=0;i<v[l].length;i++)
            {
                f[v[l][i]] = -1;
            }
              
            // Increment 'l'
            l++;
        }
        else
        {
              
            // Maximize the answer when
            // no common factor is found
            ans = Math.max(ans, r - l + 1);
            r++;
        }
          
    }
      
    // One length subarray is discarded
    if (ans == 1)
    {
        ans = -1;
    }
    return ans;
}
 
// Driver code
 
sieve();
let arr=[ 6, 10, 21];
let n = arr.length;
document.write(maxLengthSubArray(arr, n));
 
 
// This code is contributed by patel2127
</script>
Output: 
2

 




My Personal Notes arrow_drop_up