给定一个由N个正整数组成的数组arr [] ,任务是查找给定数组中由质数组成的最长递增子序列的长度。
例子:
Input: arr[] = {1, 2, 5, 3, 2, 5, 1, 7}
Output: 4
Explanation:
The Longest Increasing Prime Subsequence is {2, 3, 5, 7}.
Therefore, the answer is 4.
Input: arr[] = {6, 11, 7, 13, 9, 25}
Output: 2
Explanation:
The Longest Increasing Prime Subsequence is {11, 13} and {7, 13}.
Therefore, the answer is 2.
天真的方法:最简单的方法是生成给定数组的所有可能子序列,并按升序打印由质数组成的最长子序列的长度。
时间复杂度: O(2 N )
辅助空间: O(N)
高效方法:想法是使用动态编程方法来优化上述方法。此问题是最长增加子序列(LIS)问题的基本变体。步骤如下:
- 初始化大小为N的辅助数组dp [] ,以使dp [i]存储以索引i结尾的质数的LIS的长度。
- 以下是找到增长最长的素数的递归关系:
If arr[i] is prime then
dp[i] = 1 + max(dp[j], for j belongs (0, i – 1)), where 0 < j < i and arr[j] < arr[i];
dp[i] = 1, if no such j exists
else if arr[i] is non-prime then
dp[i] = 0 - 使用Eratosthenes筛子将所有质数存储到10 5 。
- 在给定数组上迭代两个嵌套循环,并根据上述递归关系更新数组dp [] 。
- 完成上述所有步骤后,数组dp []中的最大元素是给定数组中素数最长的递增子序列的长度。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
#define N 100005
// Function to find the prime numbers
// till 10^5 using Sieve of Eratosthenes
void SieveOfEratosthenes(bool prime[],
int p_size)
{
// False here indicates
// that it is not prime
prime[0] = false;
prime[1] = false;
for (int p = 2; p * p <= p_size; p++) {
// If prime[p] is not changed,
// then it is a prime
if (prime[p]) {
// Update all multiples of p,
// set them to non-prime
for (int i = p * 2;
i <= p_size; i += p)
prime[i] = false;
}
}
}
// Function which computes the length
// of the LIS of Prime Numbers
int LISPrime(int arr[], int n)
{
// Create an array of size n
int lisp[n];
// Create boolean array to
// mark prime numbers
bool prime[N + 1];
// Initialize all values to true
memset(prime, true, sizeof(prime));
// Precompute N primes
SieveOfEratosthenes(prime, N);
lisp[0] = prime[arr[0]] ? 1 : 0;
// Compute optimized LIS having
// prime numbers in bottom up manner
for (int i = 1; i < n; i++) {
if (!prime[arr[i]]) {
lisp[i] = 0;
continue;
}
lisp[i] = 1;
for (int j = 0; j < i; j++) {
// Check for LIS and prime
if (prime[arr[j]]
&& arr[i] > arr[j]
&& lisp[i] < lisp[j] + 1) {
lisp[i] = lisp[j] + 1;
}
}
}
// Return maximum value in lis[]
return *max_element(lisp, lisp + n);
}
// Driver Code
int main()
{
// Given array
int arr[] = { 1, 2, 5, 3, 2, 5, 1, 7 };
// Size of array
int M = sizeof(arr) / sizeof(arr[0]);
// Function Call
cout << LISPrime(arr, M);
return 0;
}
Java
// Java program for the above approach
import java.util.*;
class GFG{
static final int N = 100005;
// Function to find the prime numbers
// till 10^5 using Sieve of Eratosthenes
static void SieveOfEratosthenes(boolean prime[],
int p_size)
{
// False here indicates
// that it is not prime
prime[0] = false;
prime[1] = false;
for(int p = 2; p * p <= p_size; p++)
{
// If prime[p] is not changed,
// then it is a prime
if (prime[p])
{
// Update all multiples of p,
// set them to non-prime
for(int i = p * 2;
i <= p_size;
i += p)
prime[i] = false;
}
}
}
// Function which computes the length
// of the LIS of Prime Numbers
static int LISPrime(int arr[], int n)
{
// Create an array of size n
int []lisp = new int[n];
// Create boolean array to
// mark prime numbers
boolean []prime = new boolean[N + 1];
// Initialize all values to true
for(int i = 0; i < prime.length; i++)
prime[i] = true;
// Precompute N primes
SieveOfEratosthenes(prime, N);
lisp[0] = prime[arr[0]] ? 1 : 0;
// Compute optimized LIS having
// prime numbers in bottom up manner
for(int i = 1; i < n; i++)
{
if (!prime[arr[i]])
{
lisp[i] = 0;
continue;
}
lisp[i] = 1;
for(int j = 0; j < i; j++)
{
// Check for LIS and prime
if (prime[arr[j]] &&
arr[i] > arr[j] &&
lisp[i] < lisp[j] + 1)
{
lisp[i] = lisp[j] + 1;
}
}
}
// Return maximum value in lis[]
return Arrays.stream(lisp).max().getAsInt();
}
// Driver Code
public static void main(String[] args)
{
// Given array
int arr[] = { 1, 2, 5, 3, 2, 5, 1, 7 };
// Size of array
int M = arr.length;
// Function call
System.out.print(LISPrime(arr, M));
}
}
// This code is contributed by Amit Katiyar
Python3
# Python3 program for
# the above approach
N = 100005
# Function to find the prime numbers
# till 10^5 using Sieve of Eratosthenes
def SieveOfEratosthenes(prime, p_size):
# False here indicates
# that it is not prime
prime[0] = False
prime[1] = False
p = 2
while p * p <= p_size:
# If prime[p] is not changed,
# then it is a prime
if (prime[p]):
# Update all multiples of p,
# set them to non-prime
for i in range (p * 2,
p_size + 1, p):
prime[i] = False
p += 1
# Function which computes the length
# of the LIS of Prime Numbers
def LISPrime(arr, n):
# Create an array of size n
lisp = [0] * n
# Create boolean array to
# mark prime numbers
prime = [True] * (N + 1)
# Precompute N primes
SieveOfEratosthenes(prime, N)
if prime[arr[0]]:
lisp[0] = 1
else:
lisp[0] = 0
# Compute optimized LIS having
# prime numbers in bottom up manner
for i in range (1, n):
if (not prime[arr[i]]):
lisp[i] = 0
continue
lisp[i] = 1
for j in range (i):
# check for LIS and prime
if (prime[arr[j]] and
arr[i] > arr[j] and
lisp[i] < lisp[j] + 1):
lisp[i] = lisp[j] + 1
# Return maximum value in lis[]
return max(lisp)
# Driver Code
if __name__ == "__main__":
# Given array
arr = [1, 2, 5, 3,
2, 5, 1, 7]
# Size of array
M = len(arr)
# Function Call
print (LISPrime(arr, M))
# This code is contributed by Chitranayal
C#
// C# program for the above approach
using System;
using System.Linq;
class GFG{
static readonly int N = 100005;
// Function to find the prime numbers
// till 10^5 using Sieve of Eratosthenes
static void SieveOfEratosthenes(bool []prime,
int p_size)
{
// False here indicates
// that it is not prime
prime[0] = false;
prime[1] = false;
for(int p = 2; p * p <= p_size; p++)
{
// If prime[p] is not changed,
// then it is a prime
if (prime[p])
{
// Update all multiples of p,
// set them to non-prime
for(int i = p * 2;
i <= p_size;
i += p)
prime[i] = false;
}
}
}
// Function which computes the length
// of the LIS of Prime Numbers
static int LISPrime(int []arr, int n)
{
// Create an array of size n
int []lisp = new int[n];
// Create bool array to
// mark prime numbers
bool []prime = new bool[N + 1];
// Initialize all values to true
for(int i = 0; i < prime.Length; i++)
prime[i] = true;
// Precompute N primes
SieveOfEratosthenes(prime, N);
lisp[0] = prime[arr[0]] ? 1 : 0;
// Compute optimized LIS having
// prime numbers in bottom up manner
for(int i = 1; i < n; i++)
{
if (!prime[arr[i]])
{
lisp[i] = 0;
continue;
}
lisp[i] = 1;
for(int j = 0; j < i; j++)
{
// Check for LIS and prime
if (prime[arr[j]] &&
arr[i] > arr[j] &&
lisp[i] < lisp[j] + 1)
{
lisp[i] = lisp[j] + 1;
}
}
}
// Return maximum value in lis[]
return lisp.Max();
}
// Driver Code
public static void Main(String[] args)
{
// Given array
int []arr = { 1, 2, 5, 3, 2, 5, 1, 7 };
// Size of array
int M = arr.Length;
// Function call
Console.Write(LISPrime(arr, M));
}
}
// This code is contributed by Amit Katiyar
4
时间复杂度: O(N 2 )
辅助空间: O(N)