具有较大角值的最长子序列
给定一个包含前N个自然数的随机排列的数组arr[] ,任务是找到具有第一个和最后一个元素大于所有其他子序列元素的属性的最长子序列。
例子:
Input: arr[] = {3, 1, 5, 2, 4}
Output: 4
The sub-sequence is {3, 1, 2, 4}. The corner elements of this subsequence are greater than all other elements.
Input: arr[] = {1, 2, 3, 4, 5}
Output: 2
We cannot make a subsequence of size greater than 2.
方法:如果我们固定子序列的最左边和最右边的元素,我们感兴趣的是计算它们之间有多少元素的值小于两者。这个想法的直接实现具有 O(N 3 ) 的复杂性。
为了降低复杂性,我们以不同的方式处理问题。我们不是固定子序列的末端,而是固定它们之间的元素。这个想法是,对于给定的 X (1 ≤ X ≤ N),我们希望找到两个大于或等于 X 的元素,它们之间有尽可能多的小于 X 的元素。对于固定的 X,最好选择最左边和最右边的元素≤X。现在我们有一个更好的 O(N 2 ) 解决方案。
随着 X 的增加,最左边的元素只能增加,而最右边的元素只能减少。我们可以为它们中的每一个使用一个指针来获得 O(N) 的摊销复杂度。
下面是上述方法的实现:
C++
// C++ implementation of the approach
#include
using namespace std;
#define MAXN 100005
// Function to return the length of the
// longest required sub-sequence
int longestSubSeq(int n, int arr [])
{
int max_length = 0;
// Create a position array to find
// where an element is present
int pos[MAXN];
for (int i = 0; i < n; i++)
pos[arr[i] - 1] = i;
int left = n, right = 0;
for (int i = n - 1, num = 1; i >= 0;
i -= 1, num += 1)
{
// Store the minimum position
// to the left
left = min(left, pos[i]);
// Store the maximum position to
// the right
right = max(right, pos[i]);
// Recompute current maximum
max_length = max(max_length,
right - left - num + 3);
}
// Edge case when there is a single
// element in the sequence
if (n == 1)
max_length = 1;
return max_length;
}
// Driver code
int main()
{
int arr[] = { 1, 2, 3, 4, 5 };
int n = sizeof(arr) / sizeof(arr[0]);
cout << longestSubSeq(n, arr);
}
// This code is contributed by ihritik
Java
// Java implementation of the approach
class GFG {
static int MAXN = (int)1e5 + 5;
// Function to return the length of the
// longest required sub-sequence
static int longestSubSeq(int n, int[] arr)
{
int max_length = 0;
// Create a position array to find
// where an element is present
int[] pos = new int[MAXN];
for (int i = 0; i < n; i++)
pos[arr[i] - 1] = i;
int left = n, right = 0;
for (int i = n - 1, num = 1; i >= 0;
i -= 1, num += 1) {
// Store the minimum position
// to the left
left = Math.min(left, pos[i]);
// Store the maximum position to
// the right
right = Math.max(right, pos[i]);
// Recompute current maximum
max_length = Math.max(max_length,
right - left - num + 3);
}
// Edge case when there is a single
// element in the sequence
if (n == 1)
max_length = 1;
return max_length;
}
// Driver code
public static void main(String[] args)
{
int arr[] = { 1, 2, 3, 4, 5 };
int n = arr.length;
System.out.println(longestSubSeq(n, arr));
}
}
Python3
# Python3 implementation of the approach
MAXN = 100005
# Function to return the length of the
# longest required sub-sequence
def longestSubSeq(n, arr):
max_length = 0
# Create a position array to find
# where an element is present
pos = [0] * MAXN
for i in range (0, n):
pos[arr[i] - 1] = i
left = n
right = 0
num = 1
for i in range (n - 1, -1, -1) :
# Store the minimum position
# to the left
left = min(left, pos[i])
# Store the maximum position to
# the right
right = max(right, pos[i])
# Recompute current maximum
max_length = max(max_length,
right - left - num + 3)
num = num + 1
# Edge case when there is a single
# element in the sequence
if (n == 1) :
max_length = 1
return max_length
# Driver code
arr = [ 1, 2, 3, 4, 5 ]
n = len(arr)
print(longestSubSeq(n, arr))
# This code is contributed by ihritik
C#
// C# implementation of the approach
using System;
class GFG
{
static int MAXN = (int)1e5 + 5;
// Function to return the length of the
// longest required sub-sequence
static int longestSubSeq(int n, int[] arr)
{
int max_length = 0;
// Create a position array to find
// where an element is present
int[] pos = new int[MAXN];
for (int i = 0; i < n; i++)
pos[arr[i] - 1] = i;
int left = n, right = 0;
for (int i = n - 1, num = 1; i >= 0;
i -= 1, num += 1)
{
// Store the minimum position
// to the left
left = Math.Min(left, pos[i]);
// Store the maximum position to
// the right
right = Math.Max(right, pos[i]);
// Recompute current maximum
max_length = Math.Max(max_length,
right - left - num + 3);
}
// Edge case when there is a single
// element in the sequence
if (n == 1)
max_length = 1;
return max_length;
}
// Driver code
public static void Main()
{
int []arr = { 1, 2, 3, 4, 5 };
int n = arr.Length;
Console.WriteLine(longestSubSeq(n, arr));
}
}
// This code is contributed by Ryuga
PHP
= 0 ; $i--, $num++)
{
// Store the minimum position
// to the left
$left = min($left, $pos[$i]);
// Store the maximum position to
// the right
$right = max($right, $pos[$i]);
// Recompute current maximum
$max_length = max($max_length,
$right - $left - $num + 3);
}
// Edge case when there is a single
// element in the sequence
if ($n == 1)
$max_length = 1;
return $max_length;
}
// Driver code
$arr = array(1, 2, 3, 4, 5);
$n = sizeof($arr);
echo longestSubSeq($n, $arr);
// This code is contributed by ihritik
?>
Javascript
2