给定N个整数的数组arr [] ,任务是找到最长递增子序列的长度,以便在对原始数组进行排序时形成一个子数组。
例子:
Input: arr[] = { 2, 6, 4, 8, 2, 9 }
Output: 3
Explanation:
Sorted array: {2, 2, 4, 6, 8, 9}
All possible non-decreasing sequences of the original array are
{2}, {6}, {4}, {8}, {2}, {9}, {2, 2}, {6, 8}, {8, 9}, {6, 8, 9}.
Out of all the above subsequences, {6, 8, 9} is the longest subsequence which is a subarray in the sorted representation of the array.
Input: arr[] = { 5, 5, 6, 6, 5, 5, 5, 6, 5, 5 }
Output: 7
Explanation:
Sorted array: {5, 5, 5, 5, 5, 5, 5, 6, 6, 6}
{5, 5, 5, 5, 5, 5, 5} is the longest subequence which forms a subarray in the sorted form of the array.
天真的方法:想法是生成数组的所有可能的子序列,然后在对原始数组进行排序时检查其中哪一个形成最长的子数组。
时间复杂度: O(2 N )
辅助空间: O(N)
高效方法:想法是使用动态编程方法来解决此问题。步骤如下:
- 将每个元素的频率存储在Map中的给定数组中。
- 将原始数组存储在一个临时数组中,并对给定的数组进行排序。
- 初始化大小为N * 3的2D数组,其中:
- dp [N] [i]将存储数字X直到位置i 。
- dp [x] [1]将存储数字X的计数+数字(X – 1)的计数,直到位置i为止。
- dp [x] [2]将存储序列的实际长度,直到位置i为止。
- 遍历原始数组,并在原始数组中的每个索引i上,仅在所有(X – 1)个元素已包含在子序列中时才在当前位置i包含该元素,并更新dp [] []和在此状态之后,更新最大子序列大小。
- 完成上述步骤后,打印最大子序列大小。
下面是上述方法的实现:
C++
// C++ program to implement
// the above approach
#include
using namespace std;
// Function to find the length of the
// longest increasing sorted sequence
int LongestSequence(int a[], int n)
{
// Stores the count of all elements
map m;
int ar[n + 1], i, j;
// Store the original array
for (i = 1; i <= n; i++) {
ar[i] = a[i - 1];
}
// Sort the array
sort(a, a + n);
int c = 1;
m[a[0]] = c;
for (i = 1; i <= n; i++) {
// If adjacent element
// are not same
if (a[i] != a[i - 1]) {
// Increment count
c++;
m[a[i]] = c;
}
}
// Store frequency of each element
map cnt;
// Initialize a DP array
int dp[n + 1][3] = { 0 };
cnt[0] = 0;
// Iterate over the array ar[]
for (i = 1; i <= n; i++) {
ar[i] = m[ar[i]];
cnt[ar[i]]++;
}
// Length of the longest
// increasing sorted sequence
int ans = 0, x;
// Iterate over the array
for (i = 1; i <= n; i++) {
// Current element
x = ar[i];
// If the element has been
// encountered the first time
if (dp[x][0] == 0) {
// If all the x - 1 previous
// elements have already appeared
if (dp[x - 1][0] == cnt[x - 1]) {
dp[x][1] = dp[x - 1][1];
dp[x][2] = dp[x - 1][1];
}
// Otherwise
else {
dp[x][1] = dp[x - 1][0];
}
}
dp[x][2] = max(dp[x - 1][0],
dp[x][2]);
if (dp[x - 1][0] == cnt[x - 1]) {
// If all x-1 elements have
// already been encountered
dp[x][2] = max(dp[x][2],
dp[x - 1][1]);
}
for (j = 0; j < 3; j++) {
// Increment the count of
// the current element
dp[x][j]++;
// Update maximum
// subsequence size
ans = max(ans, dp[x][j]);
}
}
// Return the maximum
// subsequence size
return ans;
}
// Driver Code
int main()
{
int arr[] = { 2, 6, 4, 8, 2, 9 };
int N = sizeof(arr) / sizeof(arr[0]);
// Function Call
cout << LongestSequence(arr, N);
return 0;
}
Java
// Java program to implement
// the above approach
import java.io.*;
import java.util.*;
class GFG{
// Function to find the length of the
// longest increasing sorted sequence
static int LongestSequence(int a[], int n)
{
// Stores the count of all elements
HashMap m = new HashMap<>();
int ar[] = new int[n + 1];
int i = 0;
int j = 0;
// Store the original array
for(i = 1; i <= n; i++)
{
ar[i] = a[i - 1];
}
// Sort the array
Arrays.sort(a);
int c = 1;
m.put(a[0], c);
for(i = 1; i < n; i++)
{
// If adjacent element
// are not same
if (a[i] != a[i - 1])
{
// Increment count
c++;
m.put(a[i], c);
}
}
// Store frequency of each element
HashMap cnt = new HashMap<>();
// Initialize a DP array
int dp[][] = new int[n + 1][3];
cnt.put(0, 0);
// Iterate over the array ar[]
for(i = 1; i <= n; i++)
{
ar[i] = m.get(ar[i]);
if (cnt.containsKey(ar[i]))
cnt.put(ar[i], cnt.get(ar[i]) + 1);
else
cnt.put(ar[i], 1);
}
// Length of the longest
// increasing sorted sequence
int ans = 0, x;
// Iterate over the array
for(i = 1; i <= n; i++)
{
// Current element
x = ar[i];
// If the element has been
// encountered the first time
if (dp[x][0] == 0)
{
// If all the x - 1 previous
// elements have already appeared
if (dp[x - 1][0] == cnt.get(x - 1))
{
dp[x][1] = dp[x - 1][1];
dp[x][2] = dp[x - 1][1];
}
// Otherwise
else
{
dp[x][1] = dp[x - 1][0];
}
}
dp[x][2] = Math.max(dp[x - 1][0],
dp[x][2]);
if (dp[x - 1][0] == cnt.get(x - 1))
{
// If all x-1 elements have
// already been encountered
dp[x][2] = Math.max(dp[x][2],
dp[x - 1][1]);
}
for(j = 0; j < 3; j++)
{
// Increment the count of
// the current element
dp[x][j]++;
// Update maximum
// subsequence size
ans = Math.max(ans, dp[x][j]);
}
}
// Return the maximum
// subsequence size
return ans;
}
// Driver code
public static void main(String[] args)
{
int arr[] = { 2, 6, 4, 8, 2, 9 };
int n = arr.length;
System.out.println(LongestSequence(arr, n));
}
}
// This code is contributed by bikram2001jha
Python3
# Python 3 program to implement
# the above approach
# Function to find the length of the
# longest increasing sorted sequence
def LongestSequence(a, n):
# Stores the count of all elements
m = {i : 0 for i in range(100)}
ar = [0 for i in range(n + 1)]
# Store the original array
for i in range(1, n + 1):
ar[i] = a[i - 1]
# Sort the array
a.sort(reverse = False)
c = 1
m[a[0]] = c
for i in range(1, n):
# If adjacent element
# are not same
if (a[i] != a[i - 1]):
# Increment count
c += 1
m[a[i]] = c
# Store frequency of each element
cnt = {i : 0 for i in range(100)}
# Initialize a DP array
dp = [[0 for i in range(3)]
for j in range(n + 1)]
cnt[0] = 0
# Iterate over the array ar[]
for i in range(1, n + 1):
ar[i] = m[ar[i]]
cnt[ar[i]] += 1
# Length of the longest
# increasing sorted sequence
ans = 0
# Iterate over the array
for i in range(1, n + 1):
# Current element
x = ar[i]
# If the element has been
# encountered the first time
if (dp[x][0] == 0):
# If all the x - 1 previous
# elements have already appeared
if (dp[x - 1][0] == cnt[x - 1]):
dp[x][1] = dp[x - 1][1]
dp[x][2] = dp[x - 1][1]
# Otherwise
else:
dp[x][1] = dp[x - 1][0]
dp[x][2] = max(dp[x - 1][0], dp[x][2])
if (dp[x - 1][0] == cnt[x - 1]):
# If all x-1 elements have
# already been encountered
dp[x][2] = max(dp[x][2], dp[x - 1][1])
for j in range(3):
# Increment the count of
# the current element
dp[x][j] += 1
# Update maximum
# subsequence size
ans = max(ans, dp[x][j])
# Return the maximum
# subsequence size
return ans
# Driver Code
if __name__ == '__main__':
arr = [ 2, 6, 4, 8, 2, 9 ]
N = len(arr)
# Function call
print(LongestSequence(arr, N))
# This code is contributed by SURENDRA_GANGWAR
C#
// C# program to implement
// the above approach
using System.Collections.Generic;
using System;
class GFG{
// Function to find the length of the
// longest increasing sorted sequence
static int LongestSequence(int []a, int n)
{
// Stores the count of all elements
Dictionary m = new Dictionary();
int []ar = new int[n + 1];
int i = 0;
int j = 0;
// Store the original array
for(i = 1; i <= n; i++)
{
ar[i] = a[i - 1];
}
// Sort the array
Array.Sort(a);
int c = 1;
m[a[0]]= c;
for(i = 1; i < n; i++)
{
// If adjacent element
// are not same
if (a[i] != a[i - 1])
{
// Increment count
c++;
m[a[i]]= c;
}
}
// Store frequency of each element
Dictionarycnt = new Dictionary();
// Initialize a DP array
int [,]dp = new int[n + 1, 3];
cnt[0] = 0;
// Iterate over the array ar[]
for(i = 1; i <= n; i++)
{
ar[i] = m[ar[i]];
if (cnt.ContainsKey(ar[i]))
cnt[ar[i]]= cnt[ar[i]] + 1;
else
cnt[ar[i]]= 1;
}
// Length of the longest
// increasing sorted sequence
int ans = 0, x;
// Iterate over the array
for(i = 1; i <= n; i++)
{
// Current element
x = ar[i];
// If the element has been
// encountered the first time
if (dp[x, 0] == 0)
{
// If all the x - 1 previous
// elements have already appeared
if (dp[x - 1, 0] == cnt[x - 1])
{
dp[x, 1] = dp[x - 1, 1];
dp[x, 2] = dp[x - 1, 1];
}
// Otherwise
else
{
dp[x, 1] = dp[x - 1, 0];
}
}
dp[x, 2] = Math.Max(dp[x - 1, 0],
dp[x, 2]);
if (dp[x - 1, 0] == cnt[x - 1])
{
// If all x-1 elements have
// already been encountered
dp[x, 2] = Math.Max(dp[x, 2],
dp[x - 1, 1]);
}
for(j = 0; j < 3; j++)
{
// Increment the count of
// the current element
dp[x, j]++;
// Update maximum
// subsequence size
ans = Math.Max(ans, dp[x, j]);
}
}
// Return the maximum
// subsequence size
return ans;
}
// Driver code
public static void Main()
{
int []arr = { 2, 6, 4, 8, 2, 9 };
int n = arr.Length;
Console.WriteLine(LongestSequence(arr, n));
}
}
// This code is contributed by Stream_Cipher
3
时间复杂度: O(N)
辅助空间: O(N)