Longest subsequence forming an Arithmetic Progression (AP)

Given an array arr[] consisting of N integers, the task is to find the length of the longest subsequence than forms an Arithmetic Progression.

Examples:

Input: arr[] = {5, 10, 15, 20, 25, 30}
Output: 6
Explanation:
The whole set is in AP having common difference = 5.
Therefore, the length is 4.

Input: arr[] = { 20, 1, 15, 3, 10, 5, 8 }
Output: 4
Explanation:
The longest subsequence having the same difference is { 20, 15, 10, 5 }.
The above subsequence has same difference for every consecutive pairs i.e., (15 – 20) = (10 – 15) = (5 – 10) = -5.
Therefore, the length is 4.

Naive Approach: The simplest approach to solve the problem is to generate all the possible subsequences of the given array and print the length of the longest subsequence having the same difference between adjacent pairs of elements.Time 

Complexity: O(N*2N) 
Auxiliary Space: O(1)

Efficient Approach: The above approach can be optimized using Dynamic Programming. Below are the steps:



  1. Initialize an auxiliary matrix dp[][] where dp[i][j] denotes the length of subsequence starting at i and having a common difference as j.
  2. Iterate over the array using nested loops i from N – 1 till 0 and j from i+1 to N.
    • Assume that arr[i] and arr[j] are the first two elements of the sequence and let their difference be d.
    • Now, two cases arise:
      1. dp[j][d] = 0: No such sequence exists that starts with arr[j] and has its difference as d.In this case dp[i][d] = 2, as we can have only arr[i] and arr[j] in the sequence.
      2. dp[j][d] > 0: A sequence exists that starts with arr[j] and has difference between adjacent elements as d.In this case, the relation is dp[i][d] = 1 + dp[j][d].
  3. Finally, print the maximum length of all subsequences formed.

Below is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program for the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function that finds the longest
// arithmetic subsequence having the
// same absolute difference
int lenghtOfLongestAP(int A[], int n)
{
 
    // Stores the length of sequences
    // having same difference
    unordered_map<int,
                  unordered_map<int, int> >
        dp;
 
    // Stores the resultant length
    int res = 2;
 
    // Iterate over the array
    for (int i = 0; i < n; ++i) {
 
        for (int j = i + 1; j < n; ++j) {
 
            int d = A[j] - A[i];
 
            // Update length of subsequence
            dp[d][j] = dp[d].count(i)
                           ? dp[d][i] + 1
                           : 2;
 
            res = max(res, dp[d][j]);
        }
    }
 
    // Return res
    return res;
}
 
// Driver Code
int main()
{
    // Given array arr[]
    int arr[] = { 20, 1, 15, 3, 10, 5, 8 };
 
    int N = sizeof(arr) / sizeof(arr[0]);
 
    // Function Call
    cout << lenghtOfLongestAP(arr, N);
    return 0;
}

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# program to implement 
// the above approach 
using System;
using System.Collections.Generic; 
 
class GFG{
   
// Function that finds the longest
// arithmetic subsequence having the
// same absolute difference
static int lenghtOfLongestAP(int []A, int n)
{
   
    // Stores the length of sequences
    // having same difference
    Dictionary<int,
    Dictionary<int, int>> dp = new Dictionary<int,
                                   Dictionary<int, int>>();
   
    // Stores the resultant length
    int res = 2;
  
    // Iterate over the array
    for(int i = 0; i < n; ++i)
    {
        for(int j = i + 1; j < n; ++j)
        {
            int d = A[j] - A[i];
  
            // Update length of subsequence
            if (dp.ContainsKey(d))
            {
                 if (dp[d].ContainsKey(i))
                {
                    dp[d][j] = dp[d][i] + 1;   
                }
                else
                {
                    dp[d][j] = 2;
                }
            }
            else
            {
                dp[d] = new Dictionary<int, int>();
                dp[d][j] = 2;
            }
            res = Math.Max(res, dp[d][j]);
        }
    }
  
    // Return res
    return res;
}
   
// Driver Code
public static void Main(string[] args)
{
   
    // Given array arr[]
    int []arr = { 20, 1, 15, 3, 10, 5, 8 };
  
    int N = arr.Length;
  
    // Function call
    Console.Write(lenghtOfLongestAP(arr, N));
}
}
 
// This code is contributed by rutvik_56

chevron_right


Output: 

4

 

Time Complexity: O(N2)
Auxiliary Space: O(N2)

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.




My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.



Improved By : rutvik_56