📌  相关文章
📜  最长子序列,使得子序列中的每个元素都是通过将前一个元素与质数相乘而形成的

📅  最后修改于: 2021-05-05 03:22:07             🧑  作者: Mango

给定N个整数的排序数组。任务是找到最长的子序列,以使子序列中的每个元素都可以通过将任何质数乘以子序列中的前一个元素来访问。

注意:A [i] <= 10 5

例子:

方法:可以通过预存储质数直到数组中的最大数并使用基本的动态编程来解决此问题。可以按照以下步骤解决上述问题:

  • 最初将所有素数存储在任何数据结构中。
  • 将数字的索引散列在哈希图中。
  • 创建大小为N的dp [],并在每个位置将其初始化为1,因为可能的最长子序列仅为1。 dp [i]表示可以用a [i]作为起始元素形成的最长子序列的长度。
  • 从n-2进行迭代,并针对每个数字将其与所有质数相乘,直到超过a [n-1],然后执行以下操作。
  • 将数字a [i]乘以素数得到x。如果哈希映射中存在x,则重复将为dp [i] = max(dp [i],1 + dp [hash [x]])
  • 最后,在dp []数组中进行迭代并找到最大值,这将是我们的答案。

下面是上述方法的实现:

C++
// C++ program to implement the
// above approach
#include 
using namespace std;
  
// Function to pre-store primes
void SieveOfEratosthenes(int MAX, vector& 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 mpp;
    vector 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 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 mpp = new HashMap<>();
        Vector 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 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 mpp = new Dictionary();
        List primes = new List();
  
        // 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

时间复杂度:O(N log N)
辅助空间:O(N)