Given an array arr[] of N positive integers. The task is to find the length of the shortest sub-sequence such that the GCD of the subsequence is 1. If none of the sub-sequence has GCD 1, then print “-1“.
Examples:
Input: arr[] = {2, 6, 12, 3}
Output: 2
Explanation:
The GCD of 2, 3 = 1, which is the smallest length of subsequence like 2.
Input: arr[] = {2, 4}
Output: -1
Explanation:
GCD of 2, 4 = 2
Naive Approach: The idea is to generate all possible subsequences of the given array and print the length of that subsequence whose GCD is unity and has a minimum length. If none of the sub-sequences has GCD 1, then print “-1“.
Time Complexity: O(2N)
Auxiliary Space: O(1)
Another Approach: Using the Dynamic programming Tabulation method
We use a 2D matrix to store the previous computation of sub-problems and find the actual answer.
Implementation steps :
- Create a table to store the solution of the subproblems.
- Initialize the table with base cases
- Fill up the table iteratively
- Return the final solution
Implementation:
C++
#include <bits/stdc++.h>
using namespace std;
int findMinimumLength(vector< int >& a)
{
int n = a.size();
vector<vector< int > > dp(n, vector< int >(n, 0));
int gcd = a[0];
for ( int i = 1; i < n; i++) {
gcd = __gcd(gcd, a[i]);
}
if (gcd != 1) {
return -1;
}
for ( int i = 0; i < n; i++) {
dp[i][i] = 1;
}
for ( int len = 2; len <= n; len++) {
for ( int i = 0; i < n - len + 1; i++) {
int j = i + len - 1;
int g = __gcd(a[i], a[j]);
if (g == 1) {
dp[i][j] = 2;
}
else {
dp[i][j] = INT_MAX;
for ( int k = i; k < j; k++) {
dp[i][j] = min(dp[i][j],
dp[i][k] + dp[k + 1][j]);
}
}
}
}
return dp[0][n - 1];
}
int main()
{
vector< int > a = { 2, 6, 12, 3 };
int ans = findMinimumLength(a);
if (ans == -1) {
cout << -1 << endl;
}
else {
cout << ans << endl;
}
return 0;
}
|
Java
import java.util.*;
public class Main {
public static int
findMinimumLength(ArrayList<Integer> a)
{
int n = a.size();
int [][] dp = new int [n][n];
int gcd = a.get( 0 );
for ( int i = 1 ; i < n; i++) {
gcd = gcd(gcd, a.get(i));
}
if (gcd != 1 ) {
return - 1 ;
}
for ( int i = 0 ; i < n; i++) {
dp[i][i] = 1 ;
}
for ( int len = 2 ; len <= n; len++) {
for ( int i = 0 ; i < n - len + 1 ; i++) {
int j = i + len - 1 ;
int g = gcd(a.get(i), a.get(j));
if (g == 1 ) {
dp[i][j] = 2 ;
}
else {
dp[i][j] = Integer.MAX_VALUE;
for ( int k = i; k < j; k++) {
dp[i][j] = Math.min(
dp[i][j],
dp[i][k] + dp[k + 1 ][j]);
}
}
}
}
return dp[ 0 ][n - 1 ];
}
public static int gcd( int a, int b)
{
if (b == 0 ) {
return a;
}
else {
return gcd(b, a % b);
}
}
public static void main(String[] args)
{
ArrayList<Integer> a
= new ArrayList<>(Arrays.asList( 2 , 6 , 12 , 3 ));
int ans = findMinimumLength(a);
if (ans == - 1 ) {
System.out.println(- 1 );
}
else {
System.out.println(ans);
}
}
}
|
Python3
import math
def findMinimumLength(a):
n = len (a)
dp = [[ 0 ] * n for _ in range (n)]
gcd = a[ 0 ]
for i in range ( 1 , n):
gcd = math.gcd(gcd, a[i])
if gcd ! = 1 :
return - 1
for i in range (n):
dp[i][i] = 1
for length in range ( 2 , n + 1 ):
for i in range (n - length + 1 ):
j = i + length - 1
g = math.gcd(a[i], a[j])
if g = = 1 :
dp[i][j] = 2
else :
dp[i][j] = float ( 'inf' )
for k in range (i, j):
dp[i][j] = min (dp[i][j], dp[i][k] + dp[k + 1 ][j])
return dp[ 0 ][n - 1 ]
a = [ 2 , 6 , 12 , 3 ]
ans = findMinimumLength(a)
if ans = = - 1 :
print ( - 1 )
else :
print (ans)
|
Javascript
function findMinimumLength(a) {
const n = a.length;
const dp = Array.from({
length: n
}, () => new Array(n).fill(0));
let gcd = a[0];
for (let i = 1; i < n; i++) {
gcd = gcdFunc(gcd, a[i]);
}
if (gcd !== 1) {
return -1;
}
for (let i = 0; i < n; i++) {
dp[i][i] = 1;
}
for (let len = 2; len <= n; len++) {
for (let i = 0; i < n - len + 1; i++) {
const j = i + len - 1;
const g = gcdFunc(a[i], a[j]);
if (g === 1) {
dp[i][j] = 2;
} else {
dp[i][j] = Infinity;
for (let k = i; k < j; k++) {
dp[i][j] = Math.min(dp[i][j], dp[i][k] + dp[k + 1][j]);
}
}
}
}
return dp[0][n - 1];
}
function gcdFunc(a, b) {
if (b === 0) {
return a;
} else {
return gcdFunc(b, a % b);
}
}
const a = [2, 6, 12, 3];
const ans = findMinimumLength(a);
if (ans === -1) {
console.log(-1);
} else {
console.log(ans);
}
|
C#
using System;
using System.Collections.Generic;
using System.Linq;
class Program {
static int FindMinimumLength(List< int > a)
{
int n = a.Count;
int [, ] dp = new int [n, n];
int gcd = a[0];
for ( int i = 1; i < n; i++) {
gcd = Gcd(gcd, a[i]);
}
if (gcd != 1) {
return -1;
}
for ( int i = 0; i < n; i++) {
dp[i, i] = 1;
}
for ( int len = 2; len <= n; len++) {
for ( int i = 0; i < n - len + 1; i++) {
int j = i + len - 1;
int g = Gcd(a[i], a[j]);
if (g == 1) {
dp[i, j] = 2;
}
else {
dp[i, j] = int .MaxValue;
for ( int k = i; k < j; k++) {
dp[i, j] = Math.Min(
dp[i, j],
dp[i, k] + dp[k + 1, j]);
}
}
}
}
return dp[0, n - 1];
}
static int Gcd( int a, int b)
{
if (a == 0) {
return b;
}
return Gcd(b % a, a);
}
static void Main( string [] args)
{
List< int > a = new List< int >() { 2, 6, 12, 3 };
int ans = FindMinimumLength(a);
if (ans == -1) {
Console.WriteLine(-1);
}
else {
Console.WriteLine(ans);
}
}
}
|
Time Complexity: O(n^3)
Auxiliary Space: O(n^2)
Efficient Approach: There are 2 key observations for solving this problem:
- Two numbers will have their GCD equal to one only when their prime factors are different.
- Any positive number which is less than 109 can have a maximum of 9 prime factors.
For Example 2×3×5×7×11×13×17×19×23 = 22, 30, 92, 870. If we multiply this number by the next prime number, which is 29, it will be greater than 10^9.
Follow the steps below to solve the problem:
- Express the numbers as the product of its prime factors. Since we have a maximum of 9 prime factors, we can use the concept of Bitmask to store the state of the number.
For Example, prime factors of 12 are 2 and 3. This can be expressed in binary as 11 (Ignoring the preceding zeroes), meaning two prime factors are there for this number.
- For every number in the input array, check if any other number has the corresponding bit set or not. This could be achieved using Bitwise AND operation. The resultant of this operation is another state of our solution space.
- Now use the concept of Dynamic Programming to memorize the states. The idea is to use an array to store the states of the solution space. This works since only 9 bits could be set a time, and an array of size 1024 could capture all the states of the solution space.
- Every state uses dynamic programming to store the shortest way to reach that state.
- If the Bitwise AND of any two states is equal to 0, then the GCD is equal to one, i.e., if there is a possibility to reach state 0 from the current state, then it will have the minimum length sub-sequence and print that length otherwise print “-1”.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
vector< int > findPrimeFactors( int n)
{
vector< int > primeFactors(9, 0);
int j = 0;
if (n % 2 == 0) {
primeFactors[j++] = 2;
while (n % 2 == 0)
n >>= 1;
}
for ( int i = 3;
i * i <= n; i += 2) {
if (n % i == 0) {
primeFactors[j++] = i;
while (n % i == 0)
n /= i;
}
}
if (n > 2)
primeFactors[j++] = n;
vector< int > PrimeFactors(j);
for ( int i = 0; i < j; i++)
{
PrimeFactors[i] = primeFactors[i];
}
return PrimeFactors;
}
void findShortestSubsequence(vector< int > &dp, vector< int > a,
int index, vector< int > primeFactors)
{
int n = a.size();
for ( int j = index; j < n; j++) {
int bitmask = 0;
for ( int p = 0;
p < primeFactors.size(); p++) {
if ((a[j] % primeFactors[p]) == 0) {
bitmask ^= (1 << p);
}
}
for ( int i = 0; i < dp.size(); i++) {
if (dp[i] == n + 1)
continue ;
dp[bitmask & i]
= min(dp[bitmask & i],
dp[i] + 1);
}
}
}
void printMinimumLength(vector< int > a)
{
int Min = a.size() + 1;
for ( int i = 0; i < a.size() - 1; i++) {
vector< int > primeFactors
= findPrimeFactors(a[i]);
int n = primeFactors.size();
vector< int > dp(1 << n, a.size() + 1);
int setBits = (1 << n) - 1;
dp[setBits] = 1;
findShortestSubsequence(dp, a, i + 1,
primeFactors);
Min = min(dp[0], Min);
}
if (Min == (a.size() + 1))
cout << -1 << endl;
else
cout << Min << endl;
}
int main()
{
vector< int > arr = { 2, 6, 12, 3 };
printMinimumLength(arr);
return 0;
}
|
Java
import java.io.*;
import java.util.*;
class GFG {
private static int [] findPrimeFactors( int n)
{
int [] primeFactors = new int [ 9 ];
int j = 0 ;
if (n % 2 == 0 ) {
primeFactors[j++] = 2 ;
while (n % 2 == 0 )
n >>= 1 ;
}
for ( int i = 3 ;
i * i <= n; i += 2 ) {
if (n % i == 0 ) {
primeFactors[j++] = i;
while (n % i == 0 )
n /= i;
}
}
if (n > 2 )
primeFactors[j++] = n;
return Arrays.copyOfRange(primeFactors, 0 , j);
}
private static void
findShortestSubsequence( int [] dp, int [] a,
int index,
int [] primeFactors)
{
int n = a.length;
for ( int j = index; j < n; j++) {
int bitmask = 0 ;
for ( int p = 0 ;
p < primeFactors.length; p++) {
if (a[j] % primeFactors[p] == 0 ) {
bitmask ^= ( 1 << p);
}
}
for ( int i = 0 ;
i < dp.length; i++) {
if (dp[i] == n + 1 )
continue ;
dp[bitmask & i]
= Math.min(dp[bitmask & i],
dp[i] + 1 );
}
}
}
private static void
printMinimumLength( int [] a)
{
int min = a.length + 1 ;
for ( int i = 0 ;
i < a.length - 1 ; i++) {
int [] primeFactors
= findPrimeFactors(a[i]);
int n = primeFactors.length;
int [] dp = new int [ 1 << n];
Arrays.fill(dp, a.length + 1 );
int setBits = ( 1 << n) - 1 ;
dp[setBits] = 1 ;
findShortestSubsequence(dp, a, i + 1 ,
primeFactors);
min = Math.min(dp[ 0 ], min);
}
if (min == a.length + 1 )
System.out.println(- 1 );
else
System.out.println(min);
}
public static void main(String[] args)
{
int [] arr = { 2 , 6 , 12 , 3 };
printMinimumLength(arr);
}
}
|
Python3
def findPrimeFactors(n):
primeFactors = [ 0 for i in range ( 9 )]
j = 0
if (n % 2 = = 0 ):
primeFactors[j] = 2
j + = 1
while (n % 2 = = 0 ):
n >> = 1
i = 3
while (i * i < = n):
if (n % i = = 0 ):
primeFactors[j] = i
j + = 1
while (n % i = = 0 ):
n / / = i
i + = 2
if (n > 2 ):
primeFactors[j] = n
j + = 1
for i in range ( 0 , j + 1 ):
primeFactors[i] = 0
return primeFactors
def findShortestSubsequence(dp, a, index,
primeFactors):
n = len (a)
for j in range (index, n):
bitmask = 0
for p in range ( len (primeFactors)):
if (primeFactors[p] ! = 0 and
a[j] % primeFactors[p] = = 0 ):
bitmask ^ = ( 1 << p)
for i in range ( len (dp)):
if (dp[i] = = n + 1 ):
continue
dp[bitmask & i] = min (dp[bitmask & i],
dp[i] + 1 )
def printMinimumLength(a):
mn = len (a) + 1
for i in range ( len (a) - 1 ):
primeFactors = findPrimeFactors(a[i])
n = len (primeFactors)
dp = [ 0 for i in range ( 1 << n)]
dp = [ len (a) + 1 for i in range ( len (dp))]
setBits = ( 1 << n) - 1
dp[setBits] = 1
findShortestSubsequence(dp, a, i + 1 ,
primeFactors)
mn = min (dp[ 0 ], mn)
if (mn = = len (a) + 1 ):
print ( - 1 )
else :
print (mn)
if __name__ = = '__main__' :
arr = [ 2 , 6 , 12 , 3 ]
printMinimumLength(arr)
|
Javascript
<script>
function findPrimeFactors(n)
{
let primeFactors = new Array(9).fill(0);
let j = 0;
if (n % 2 == 0) {
primeFactors[j++] = 2;
while (n % 2 == 0)
n >>= 1;
}
for (let i = 3;
i * i <= n; i += 2) {
if (n % i == 0) {
primeFactors[j++] = i;
while (n % i == 0)
n /= i;
}
}
if (n > 2)
primeFactors[j++] = n;
let PrimeFactors = new Array(j);
for (let i = 0; i < j; i++)
{
PrimeFactors[i] = primeFactors[i];
}
return PrimeFactors;
}
function findShortestSubsequence(dp, a, index, primeFactors)
{
let n = a.length;
for (let j = index; j < n; j++) {
let bitmask = 0;
for (let p = 0;
p < primeFactors.length; p++) {
if ((a[j] % primeFactors[p]) == 0) {
bitmask ^= (1 << p);
}
}
for (let i = 0; i < dp.length; i++) {
if (dp[i] == n + 1)
continue ;
dp[bitmask & i]
= Math.min(dp[bitmask & i], dp[i] + 1);
}
}
}
function prletMinimumLength(a)
{
let Min = a.length + 1;
for (let i = 0; i < a.length - 1; i++) {
let primeFactors = findPrimeFactors(a[i]);
let n = primeFactors.length;
let dp = new Array(1 << n);
for (let i = 0; i < dp.length; i++){
dp[i] = a.length + 1
}
let setBits = (1 << n) - 1;
dp[setBits] = 1;
findShortestSubsequence(dp, a, i + 1,
primeFactors);
Min = Math.min(dp[0], Min);
}
if (Min == (a.length + 1))
document.write(-1 + "<br>" );
else
document.write(Min + "<br>" );
}
let arr = [ 2, 6, 12, 3 ];
prletMinimumLength(arr);
</script>
|
C#
using System;
class GFG{
private static int [] findPrimeFactors( int n)
{
int [] primeFactors = new int [9];
int j = 0;
if (n % 2 == 0)
{
primeFactors[j++] = 2;
while (n % 2 == 0)
n >>= 1;
}
for ( int i = 3;
i * i <= n; i += 2)
{
if (n % i == 0)
{
primeFactors[j++] = i;
while (n % i == 0)
n /= i;
}
}
if (n > 2)
primeFactors[j++] = n;
int []temp = new int [j];
Array.Copy(primeFactors, temp, j);
return temp;
}
private static void findShortestSubsequence( int [] dp, int [] a,
int index,
int [] primeFactors)
{
int n = a.Length;
for ( int j = index; j < n; j++)
{
int bitmask = 0;
for ( int p = 0;
p < primeFactors.Length; p++)
{
if (a[j] % primeFactors[p] == 0)
{
bitmask ^= (1 << p);
}
}
for ( int i = 0;
i < dp.Length; i++)
{
if (dp[i] == n + 1)
continue ;
dp[bitmask & i] = Math.Min(dp[bitmask & i],
dp[i] + 1);
}
}
}
private static void printMinimumLength( int [] a)
{
int min = a.Length + 1;
for ( int i = 0;
i < a.Length - 1; i++)
{
int [] primeFactors = findPrimeFactors(a[i]);
int n = primeFactors.Length;
int [] dp = new int [1 << n];
for (i = 0; i < dp.Length; i++)
dp[i] = a.Length + 1;
int setBits = (1 << n) - 1;
dp[setBits] = 1;
findShortestSubsequence(dp, a, i + 1,
primeFactors);
min = Math.Min(dp[0], min);
}
if (min == a.Length + 1)
Console.WriteLine(-1);
else
Console.WriteLine(min);
}
public static void Main(String[] args)
{
int [] arr = {2, 6, 12, 3};
printMinimumLength(arr);
}
}
|
Time Complexity: O(N2)
Auxiliary Space: O(2^k) where k is the number of factors of array elements.
Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!
Last Updated :
17 Apr, 2023
Like Article
Save Article