Given a sorted array of N integers. The task is to find the longest subsequence such that every element in the subsequence is reachable by multiplying any prime number to the previous element in the subsequence.
Note: A[i] <= 105
Examples:
Input: a[] = {3, 5, 6, 12, 15, 36}
Output 4
The longest subsequence is {3, 6, 12, 36}
6 = 3*2
12 = 6*2
36 = 12*32 and 3 are primes
Input: a[] = {1, 2, 5, 6, 12, 35, 60, 385}
Output: 5
Approach: The problem can be solved using pre-storing primes till the largest number in the array and using basic Dynamic Programming. The following steps can be followed to solve the above problem:
- Initially store all the primes in any of the Data-structure.
- Hash the index of the numbers in a hash-map.
- Create a dp[] of size N, and initialize it with 1 at every place, as the longest subsequence possible is 1 only. dp[i] represents the length of the longest subsequence that can be formed with a[i] as the starting element.
- Iterate from the n-2, and for every number multiply it with all the primes till it exceeds a[n-1] and perform the below operations.
- Multiply the number a[i] with prime to get x. If x exists in the hash-map then the recurrence will be dp[i] = max(dp[i], 1 + dp[hash[x]]).
- At the end, iterate in dp[] array and find the maximum value which will be our answer.
Below is the implementation of the above approach:
C++
// C++ program to implement the // above approach #include <bits/stdc++.h> using namespace std; // Function to pre-store primes void SieveOfEratosthenes( int MAX, vector< int >& primes) { bool prime[MAX + 1]; memset (prime, true , sizeof (prime)); // Sieve method to check if prime or not for ( long long p = 2; p * p <= MAX; p++) { if (prime[p] == true ) { // Multiples for ( long long i = p * p; i <= MAX; i += p) prime[i] = false ; } } // Pre-store all the primes for ( long long i = 2; i <= MAX; i++) { if (prime[i]) primes.push_back(i); } } // Function to find the longest subsequence int findLongest( int A[], int n) { // Hash map unordered_map< int , int > mpp; vector< int > primes; // Call the function to pre-store the primes SieveOfEratosthenes(A[n - 1], primes); int dp[n]; memset (dp, 0, sizeof dp); // Initialize last element with 1 // as that is the longest possible dp[n - 1] = 1; mpp[A[n - 1]] = n - 1; // Iterate from the back and find the longest for ( int i = n - 2; i >= 0; i--) { // Get the number int num = A[i]; // Initialize dp[i] as 1 // as the element will only me in // the subsequence . dp[i] = 1; int maxi = 0; // Iterate in all the primes and // multiply to get the next element for ( auto it : primes) { // Next element if multiplied with it int xx = num * it; // If exceeds the last element // then break if (xx > A[n - 1]) break ; // If the number is there in the array else if (mpp[xx] != 0) { // Get the maximum most element dp[i] = max(dp[i], 1 + dp[mpp[xx]]); } } // Hash the element mpp[A[i]] = i; } int ans = 1; // Find the longest for ( int i = 0; i < n; i++) { ans = max(ans, dp[i]); } return ans; } // Driver Code int main() { int a[] = { 1, 2, 5, 6, 12, 35, 60, 385 }; int n = sizeof (a) / sizeof (a[0]); cout << findLongest(a, n); } |
Java
// Java program to implement the // above approach import java.util.HashMap; import java.util.Vector; class GFG { // Function to pre-store primes public static void SieveOfEratosthenes( int MAX, Vector<Integer> primes) { boolean [] prime = new boolean [MAX + 1 ]; for ( int i = 0 ; i < MAX + 1 ; i++) prime[i] = true ; // Sieve method to check if prime or not for ( int p = 2 ; p * p <= MAX; p++) { if (prime[p] == true ) { // Multiples for ( int i = p * p; i <= MAX; i += p) prime[i] = false ; } } // Pre-store all the primes for ( int i = 2 ; i <= MAX; i++) { if (prime[i]) primes.add(i); } } // Function to find the intest subsequence public static int findLongest( int [] A, int n) { // Hash map HashMap<Integer, Integer> mpp = new HashMap<>(); Vector<Integer> primes = new Vector<>(); // Call the function to pre-store the primes SieveOfEratosthenes(A[n - 1 ], primes); int [] dp = new int [n]; // Initialize last element with 1 // as that is the intest possible dp[n - 1 ] = 1 ; mpp.put(A[n - 1 ], n - 1 ); // Iterate from the back and find the intest for ( int i = n - 2 ; i >= 0 ; i--) { // Get the number int num = A[i]; // Initialize dp[i] as 1 // as the element will only me in // the subsequence . dp[i] = 1 ; int maxi = 0 ; // Iterate in all the primes and // multiply to get the next element for ( int it : primes) { // Next element if multiplied with it int xx = num * it; // If exceeds the last element // then break if (xx > A[n - 1 ]) break ; // If the number is there in the array else if (mpp.get(xx) != null && mpp.get(xx) != 0 ) { // Get the maximum most element dp[i] = Math.max(dp[i], 1 + dp[mpp.get(xx)]); } } // Hash the element mpp.put(A[i], i); } int ans = 1 ; // Find the intest for ( int i = 0 ; i < n; i++) ans = Math.max(ans, dp[i]); return ans; } // Driver code public static void main(String[] args) { int [] a = { 1 , 2 , 5 , 6 , 12 , 35 , 60 , 385 }; int n = a.length; System.out.println(findLongest(a, n)); } } // This code is contributed by // sanjeev2552 |
Python3
# Python3 program to implement the # above approach from math import sqrt # Function to pre-store primes def SieveOfEratosthenes( MAX , primes) : prime = [ True ] * ( MAX + 1 ); # Sieve method to check if prime or not for p in range ( 2 , int (sqrt( MAX )) + 1 ) : if (prime[p] = = True ) : # Multiples for i in range (p * * 2 , MAX + 1 , p) : prime[i] = False ; # Pre-store all the primes for i in range ( 2 , MAX + 1 ) : if (prime[i]) : primes.append(i); # Function to find the longest subsequence def findLongest(A, n) : # Hash map mpp = {}; primes = []; # Call the function to pre-store the primes SieveOfEratosthenes(A[n - 1 ], primes); dp = [ 0 ] * n ; # Initialize last element with 1 # as that is the longest possible dp[n - 1 ] = 1 ; mpp[A[n - 1 ]] = n - 1 ; # Iterate from the back and find the longest for i in range (n - 2 , - 1 , - 1 ) : # Get the number num = A[i]; # Initialize dp[i] as 1 # as the element will only me in # the subsequence dp[i] = 1 ; maxi = 0 ; # Iterate in all the primes and # multiply to get the next element for it in primes : # Next element if multiplied with it xx = num * it; # If exceeds the last element # then break if (xx > A[n - 1 ]) : break ; # If the number is there in the array elif xx in mpp : # Get the maximum most element dp[i] = max (dp[i], 1 + dp[mpp[xx]]); # Hash the element mpp[A[i]] = i; ans = 1 ; # Find the longest for i in range (n) : ans = max (ans, dp[i]); return ans; # Driver Code if __name__ = = "__main__" : a = [ 1 , 2 , 5 , 6 , 12 , 35 , 60 , 385 ]; n = len (a); print (findLongest(a, n)); # This code is contributed by AnkitRai01 |
C#
// C# program to implement the // above approach using System; using System.Collections.Generic; class GFG { // Function to pre-store primes public static void SieveOfEratosthenes( int MAX, List< int > primes) { Boolean[] prime = new Boolean[MAX + 1]; for ( int i = 0; i < MAX + 1; i++) prime[i] = true ; // Sieve method to check if prime or not for ( int p = 2; p * p <= MAX; p++) { if (prime[p] == true ) { // Multiples for ( int i = p * p; i <= MAX; i += p) prime[i] = false ; } } // Pre-store all the primes for ( int i = 2; i <= MAX; i++) { if (prime[i]) primes.Add(i); } } // Function to find the intest subsequence public static int findLongest( int [] A, int n) { // Hash map Dictionary< int , int > mpp = new Dictionary< int , int >(); List< int > primes = new List< int >(); // Call the function to pre-store the primes SieveOfEratosthenes(A[n - 1], primes); int [] dp = new int [n]; // Initialize last element with 1 // as that is the intest possible dp[n - 1] = 1; mpp.Add(A[n - 1], n - 1); // Iterate from the back and find the intest for ( int i = n - 2; i >= 0; i--) { // Get the number int num = A[i]; // Initialize dp[i] as 1 // as the element will only me in // the subsequence . dp[i] = 1; // Iterate in all the primes and // multiply to get the next element foreach ( int it in primes) { // Next element if multiplied with it int xx = num * it; // If exceeds the last element // then break if (xx > A[n - 1]) break ; // If the number is there in the array else if (mpp.ContainsKey(xx) && mpp[xx] != 0) { // Get the maximum most element dp[i] = Math.Max(dp[i], 1 + dp[mpp[xx]]); } } // Hash the element if (mpp.ContainsKey(A[i])) mpp[A[i]] = i; else mpp.Add(A[i], i); } int ans = 1; // Find the intest for ( int i = 0; i < n; i++) ans = Math.Max(ans, dp[i]); return ans; } // Driver code public static void Main(String[] args) { int [] a = { 1, 2, 5, 6, 12, 35, 60, 385 }; int n = a.Length; Console.WriteLine(findLongest(a, n)); } } // This code is contributed by Rajput-Ji |
5
Time Complexity: O(N log N)
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.