Longest non-decreasing Subsequence with adjacent differences
Last Updated :
25 Aug, 2023
Given an array arr[] of N elements, the task is to find the length of the longest non-decreasing subsequence such that the differences between adjacent elements are non-decreasing. For indices i, j, and k:
i < j < k, ai − aj ≤ aj − ak
Examples:
Input: N = 9, arr[] = [1, 3, 5, 4, 7, 8, 10, 6, 9]
Output: 6
Explanation: Longest non-decreasing Subsequence is [1, 3, 5, 7, 8, 10]. Here, the subsequence satisfies the given condition, (3 – 1) <= (5 – 3), (4 – 3) <= (5 – 4), (7 – 5) <= (8 – 7), (8 – 7) <= (10 – 8), and (10 – 8) <= (9 – 6). The length of such Longest Subsequence in this case is 6.
Input: N = 8, arr[] = [1, 4, 5, 6, 2, 3, 8, 9]
Output: 5
Explanation: Longest non-decreasing Subsequence with given condition is [1, 4, 6, 8, 9].
Approach: To solve the problem follow the below idea:
The idea is to use a dp array to store the length of such longest subsequence up to index i of the given array. Then, we traverse the array for each index i, and for each index j (0 ≤ j < i), we check if the subsequence [j, i] forms a subsequence. If it does, we update the value of dp[i] with the maximum value of dp[j]+1. Finally, we return the maximum value in the dp array.
Below are the steps for the above approach:
- Initialize a variable say n to store the size of the input array arr.
- Check if the size of the given array is less than or equal to 2, and return the size of the array.
- Initialize an array dp of size n all 0’s.
- Initialize the first two values of the dp to 1 and 2 respectively.
- Initialize a variable say ans = 2.
- Iterate from index i = 2 to i < n,
- Inside the for loop, run another loop from index j = 1 to j < i
- Check if the current element and the previous element form a subsequence with the given condition, if (arr[i] – arr[j] == arr[j] – arr[j-1]),
- Update the dp[] array with the maximum value between the current dp value of i and dp value of j + 1.
- Update the ans variable with the maximum value between itself and the current dp value of i.
- Return ans.
Below is the implementation for the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int longest_subsequence(vector< int > arr)
{
int n = arr.size();
if (n <= 2)
return n;
int dp[n];
memset (dp, 0, sizeof (dp));
dp[0] = 1;
dp[1] = 2;
int ans = 2;
for ( int i = 2; i < n; i++) {
for ( int j = 1; j < i; j++) {
if (arr[i] - arr[j] == arr[j] - arr[j - 1])
dp[i] = max(dp[i], dp[j] + 1);
}
ans = max(ans, dp[i]);
}
return ans;
}
int main()
{
vector< int > arr = { 1, 2, 3, 5, 6, 8 };
cout << "Longest Subsequence: "
<< longest_subsequence(arr) << endl;
return 0;
}
|
Java
import java.util.Arrays;
public class LongestConvexSubsequence {
public static int longestConvexSubsequence( int [] arr)
{
int n = arr.length;
if (n <= 2 )
return n;
int [] dp = new int [n];
Arrays.fill(dp, 2 );
int ans = 2 ;
for ( int i = 2 ; i < n; i++) {
for ( int j = 1 ; j < i; j++) {
if (arr[i] - arr[j] == arr[j] - arr[j - 1 ])
dp[i] = Math.max(dp[i], dp[j] + 1 );
}
ans = Math.max(ans, dp[i]);
}
return ans;
}
public static void main(String[] args)
{
int [] arr = { 1 , 2 , 3 , 5 , 6 , 8 };
System.out.println( "Longest Convex Subsequence: " + longestConvexSubsequence(arr));
}
}
|
Python3
def longest_convex_subsequence(arr):
n = len (arr)
if n < = 2 :
return n
dp = [ 2 ] * n
ans = 2
for i in range ( 2 , n):
for j in range ( 1 , i):
if arr[i] - arr[j] = = arr[j] - arr[j - 1 ]:
dp[i] = max (dp[i], dp[j] + 1 )
ans = max (ans, dp[i])
return ans
arr = [ 1 , 2 , 3 , 5 , 6 , 8 ]
print ( "Longest Convex Subsequence: " , longest_convex_subsequence(arr))
|
C#
using System;
using System.Collections.Generic;
class Program
{
static int LongestSubsequence(List< int > arr)
{
int n = arr.Count;
if (n <= 2)
return n;
int [] dp = new int [n];
dp[0] = 1;
dp[1] = 2;
int ans = 2;
for ( int i = 2; i < n; i++)
{
for ( int j = 1; j < i; j++)
{
if (arr[i] - arr[j] == arr[j] - arr[j - 1])
{
dp[i] = Math.Max(dp[i], dp[j] + 1);
}
}
ans = Math.Max(ans, dp[i]);
}
return ans;
}
static void Main()
{
List< int > arr = new List< int > { 1, 2, 3, 5, 6, 8 };
Console.WriteLine( "Longest Subsequence: " + LongestSubsequence(arr));
}
}
|
Javascript
function longestSubsequence(arr) {
const n = arr.length;
if (n <= 2) {
return n;
}
const dp = Array(n).fill(0);
dp[0] = 1;
dp[1] = 2;
let ans = 2;
for (let i = 2; i < n; i++) {
for (let j = 1; j < i; j++) {
if (arr[i] - arr[j] === arr[j] - arr[j - 1]) {
dp[i] = Math.max(dp[i], dp[j] + 1);
}
}
ans = Math.max(ans, dp[i]);
}
return ans;
}
const arr = [1, 2, 3, 5, 6, 8];
console.log( "Longest Subsequence:" , longestSubsequence(arr));
|
Output
Longest Subsequence: 3
Time Complexity: O(n2)
Auxiliary Space: O(n), where n is the length of the given array.
Greedy Approach: To solve the problem follow the below idea:
The idea is to use a variable ‘len’ to store the length of the longest subsequence seen so far, and another variable ‘curr_len’ to store the length of the current subsequence. Also, use a variable ‘diff’ to store the difference between two consecutive elements of the current subsequence. Initialize ‘len’ and ‘curr_len’ with 2, as any two elements form a subsequence. Traverse the array and check if the difference between two consecutive elements is the same as the ‘diff’ variable, increment ‘curr_len’, else, update the ‘len’ variable with the maximum value between ‘len’ and ‘curr_len’, and reset ‘curr_len’ to 2, and ‘diff’ to the difference between the two consecutive elements. Return the maximum value between ‘len’ and ‘curr_len’.
Below are the steps for the above approach:
- Initialize a variable say n to store the size of the input array arr.
- Check if the size of the given array is less than or equal to 2, and return the size of the array.
- Initialize a variable len = 2, as the length of the smallest subsequence, is 2.
- Initialize a variable diff to the difference between the second and the first elements of the input array arr.
- Initialize the current length of subsequence as 2, curr_len = 2.
- Traverse the array from index i = 2 to i < n and check if the difference between the current element and the previous element is the same as the difference between the previous two elements, increment curr_length by 1.
- Else if the difference between the current element and the previous element is not the same as the difference between the previous two elements, update the difference between the consecutive elements, diff = arr[i] – arr[i-1].
- Update length of longest subsequence, len = max(len, curr_len).
- The current length of the subsequence is reset to 2.
- Once the for loop completes, the length of the longest subsequence is updated by taking the maximum value between itself and the current length of the subsequence, len = max(len, curr_len).
- Return the value of variable len.
Below is the implementation for the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int longest_subsequence(vector< int > arr)
{
int n = arr.size();
if (n <= 2)
return n;
int len = 2;
int diff = arr[1] - arr[0];
int curr_len = 2;
for ( int i = 2; i < n; i++) {
if (arr[i] - arr[i - 1] == diff) {
curr_len++;
}
else {
diff = arr[i] - arr[i - 1];
len = max(len, curr_len);
curr_len = 2;
}
}
len = max(len, curr_len);
return len;
}
int main()
{
vector< int > arr = { 1, 2, 3, 5, 6, 8 };
cout << "Longest non-decreasing Subsequence: "
<< longest_subsequence(arr) << endl;
return 0;
}
|
Java
import java.util.Arrays;
public class LongestConvexSubsequence {
public static int longestConvexSubsequence( int [] arr)
{
int n = arr.length;
if (n <= 2 )
return n;
int len = 2 ;
int diff = arr[ 1 ] - arr[ 0 ];
int curr_len = 2 ;
for ( int i = 2 ; i < n; i++) {
if (arr[i] - arr[i - 1 ] == diff) {
curr_len++;
}
else {
diff = arr[i] - arr[i - 1 ];
len = Math.max(len, curr_len);
curr_len = 2 ;
}
}
len = Math.max(len, curr_len);
return len;
}
public static void main(String[] args)
{
int [] arr = { 1 , 2 , 3 , 5 , 6 , 8 };
System.out.println( "Longest Convex Subsequence: " + longestConvexSubsequence(arr));
}
}
|
Python3
def longest_convex_subsequence(arr):
n = len (arr)
if n < = 2 :
return n
max_len = 2
diff = arr[ 1 ] - arr[ 0 ]
curr_len = 2
for i in range ( 2 , n):
if arr[i] - arr[i - 1 ] = = diff:
curr_len + = 1
else :
diff = arr[i] - arr[i - 1 ]
max_len = max (max_len, curr_len)
curr_len = 2
max_len = max (max_len, curr_len)
return max_len
arr = [ 1 , 2 , 3 , 5 , 6 , 8 ]
print ( "Longest Convex Subsequence: " , longest_convex_subsequence(arr))
|
C#
using System;
using System.Collections.Generic;
class Program {
static void Main( string [] args)
{
int [] arr = { 1, 2, 3, 5, 6, 8 };
Console.WriteLine( "Longest Convex Subsequence: "
+ longestConvexSubsequence(arr));
}
public static int longestConvexSubsequence( int [] arr)
{
int n = arr.Length;
if (n <= 2)
return n;
int len = 2;
int diff = arr[1]
- arr[0];
int curr_len = 2;
for ( int i = 2; i < n; i++) {
if (arr[i] - arr[i - 1] == diff) {
curr_len++;
}
else {
diff
= arr[i]
- arr[i - 1];
len = Math.Max(
len,
curr_len);
curr_len = 2;
}
}
len = Math.Max(
len,
curr_len);
return len;
}
}
|
Javascript
function longest_subsequence(arr) {
let n = arr.length;
if (n <= 2)
return n;
let len = 2;
let diff = arr[1] - arr[0];
let curr_len = 2;
for (let i = 2; i < n; i++) {
if (arr[i] - arr[i - 1] == diff) {
curr_len++;
}
else {
diff = arr[i] - arr[i - 1];
len = Math.max(len, curr_len);
curr_len = 2;
}
}
len = Math.max(len, curr_len);
return len;
}
let arr = [1, 2, 3, 5, 6, 8];
console.log( "Longest non-decreasing Subsequence: " + longest_subsequence(arr));
|
Output
Longest non-decreasing Subsequence: 3
Time Complexity: O(n), where n is the length of the given array.
Auxiliary Space: O(1), since we are not using any additional data structures.
Share your thoughts in the comments
Please Login to comment...