Open In App

Longest Arithmetic Progression

Improve
Improve
Like Article
Like
Save
Share
Report

Given an array Set[ ] of sorted integers having no duplicates, find the length of the Longest Arithmetic Progression (LLAP) subsequence in it.

Examples: 

Input: Set[] = {1, 7, 10, 15, 27, 29}
Output: 3
Explanation: The longest arithmetic progression is {1, 15, 29} having common difference 14.

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

Approach 1: Brute forcing the solution in O(N^3)

A simple solution is to one by one consider every pair as first two elements of AP and check for the remaining elements in sorted array. To consider all pairs as first two elements, we need to run a O(n^2) nested loop. Inside the nested loops, we need a third loop which linearly looks for the more elements in Arithmetic Progression (AP). This process takes O(n3) time. 
We can solve this problem in O(n2) time using Dynamic Programming. To get idea of the DP solution, let us first discuss solution of following simpler problem.

Given a sorted Array, find if there exist three elements in Arithmetic Progression or not: 

Please note that, the answer is true if there are 3 or more elements in AP, otherwise false. To find the three elements, we first fix an element as middle element and search for other two (one smaller and one greater). We start from the second element and fix every element as middle element.

For an element set[j] to be middle of AP, there must exist elements ‘set[i]’ and ‘set[k]’ such that set[i] + set[k] = 2*set[j] where 0 <= i < j and j < k <=n-1. 

Algorithm to efficiently find i and k for a given j: 

We can find i and k in linear time using following simple algorithm. 

  • Initialize i as j-1 and k as j+1
  • Do following while i >= 0 and k <= n-1
    • If set[i] + set[k] is equal to 2*set[j], then we are done.
    • If set[i] + set[k] > 2*set[j], then decrement i (do i–).
    • Else if set[i] + set[k] < 2*set[j], then increment k (do k++).

Following is the implementation of the above algorithm for the simpler problem.  

C++




// The function returns true if there exist three
// elements in AP Assumption: set[0..n-1] is sorted.
// The code strictly implements the algorithm provided
// in the reference.
bool arithmeticThree(vector<int> set, int n)
{
     
    // One by fix every element as middle element
    for(int j = 1; j < n - 1; j++)
    {
         
        // Initialize i and k for the current j
        int i = j - 1, k = j + 1;
 
        // Find if there exist i and k that form AP
        // with j as middle element
        while (i >= 0 && k <= n-1)
        {
            if (set[i] + set[k] == 2 * set[j])
                return true;
                 
            (set[i] + set[k] < 2 * set[j]) ? k++ : i--;
        }
    }
    return false;
}
 
// This code is contributed by Samim Hossain Mondal.


C




// The function returns true if there exist three elements in AP
// Assumption: set[0..n-1] is sorted.
// The code strictly implements the algorithm provided in the reference.
bool arithmeticThree(int set[], int n)
{
    // One by fix every element as middle element
    for (int j=1; j<n-1; j++)
    {
        // Initialize i and k for the current j
        int i = j-1, k = j+1;
 
        // Find if there exist i and k that form AP
        // with j as middle element
        while (i >= 0 && k <= n-1)
        {
            if (set[i] + set[k] == 2*set[j])
                return true;
            (set[i] + set[k] < 2*set[j])? k++ : i--;
        }
    }
 
    return false;
}


Java




// The function returns true if there exist three elements in AP
// Assumption: set[0..n-1] is sorted.
// The code strictly implements the algorithm provided in the reference.
static boolean arithmeticThree(int set[], int n)
{
    // One by fix every element as middle element
    for (int j = 1; j < n - 1; j++)
    {
        // Initialize i and k for the current j
        int i = j - 1, k = j + 1;
 
        // Find if there exist i and k that form AP
        // with j as middle element
        while (i >= 0 && k <= n-1)
        {
            if (set[i] + set[k] == 2*set[j])
                return true;
            (set[i] + set[k] < 2*set[j])? k++ : i--;
        }
    }
 
    return false;
}
 
// This code is contributed by gauravrajput1


C#




// The function returns true if there exist three elements in AP
// Assumption: set[0..n-1] is sorted.
// The code strictly implements the algorithm provided in the reference.
static bool arithmeticThree(int []set, int n)
{
   
    // One by fix every element as middle element
    for (int j = 1; j < n - 1; j++)
    {
       
        // Initialize i and k for the current j
        int i = j - 1, k = j + 1;
 
        // Find if there exist i and k that form AP
        // with j as middle element
        while (i >= 0 && k <= n-1)
        {
            if (set[i] + set[k] == 2*set[j])
                return true;
            if(set[i] + set[k] < 2*set[j])
                k++;
            else
                i--;
        }
    }
 
    return false;
}
 
// This code is contributed by gauravrajput1


Javascript




<script>
// The function returns true if there exist three elements in AP
// Assumption: set[0..n-1] is sorted.
// The code strictly implements the algorithm provided in the reference.
function arithmeticThree(set, n){
    // One by fix every element as middle element
    for (let j=1; j<n-1; j++)
    {
        // Initialize i and k for the current j
        let i = j-1, k = j+1;
 
        // Find if there exist i and k that form AP
        // with j as middle element
        while (i >= 0 && k <= n-1)
        {
            if (set[i] + set[k] == 2*set[j])
                return true;
            (set[i] + set[k] < 2*set[j])? k++ : i--;
        }
    }
 
    return false;
}
</script>


Python3




# The function returns true if there exist three elements in AP
# Assumption: set[0..n-1] is sorted.
# The code strictly implements the algorithm provided in the reference.
def arithematicThree(set_,n):
 
    # One by fix every element as middle element
    for j in range(n):
         
        # Initialize i and k for the current j
        i,k=j-1,j+1
 
        # Find if there exist i and k that form AP
        # with j as middle element
        while i>-1 and k<n:
            if set_[i]+set_[k] == 2*set_[j]:
                return True
               
            elif set_[i]+set_[k]<2*set_[j]:
                i-=1
                 
            else:
                k+=1
    return False
  # This code is contributed by Kushagra Bansal


Longest Arithmetic Progression using Dynamic Programming

Iteratively examining all possible pairs of elements as the first two elements of an AP and then extending the AP to find the longest one. The algorithm uses a dynamic programming approach to store the length of the LLAP ending at each pair of elements. It starts with a minimum LLAP length of 2 (two elements), and as it iterates through the elements, it updates and keeps track of the maximum LLAP length found so far. Finally, it returns the length of the longest arithmetic progression found in the set.

The below image shows how the dp table fills for the array [1, 7, 10, 13, 14, 19].

LLAP-dp-35

Step-by-step approach:

  • Initialize a 2D array L[][] to store the length of LLAPs ending at pairs of elements.
  • For each element in the set, fill the last column of L[][] with 2 since any pair forms an AP of length 2.
  • Starting from the second-to-last column, iterate through pairs of elements (set[i], set[j]).
  • Within the loop, compare set[i] + set[k] to 2 * set[j]:
    • If less, increment k to consider a larger element.
    • If greater, decrement i to consider a smaller element.
    • If equal, extend the LLAP by setting L[i][j] to L[j][k] + 1 and update the maximum LLAP length (llap).
  • Handle cases where k exceeds the last index by filling in remaining cells in the column with 2.
  • Return the maximum LLAP length (llap) found in the set.

Following is the implementation of the Dynamic Programming algorithm. 

C++




// C++ program to find Length of the Longest AP (llap) in a given sorted set.
// The code strictly implements the algorithm provided in the reference.
#include <iostream>
using namespace std;
 
// Returns length of the longest AP subset in a given set
int lenghtOfLongestAP(int set[], int n)
{
    if (n <= 2)  return n;
 
    // Create a table and initialize all values as 2. The value of
    // L[i][j] stores LLAP with set[i] and set[j] as first two
    // elements of AP. Only valid entries are the entries where j>i
    int L[n][n];
    int llap = 2;  // Initialize the result
 
    // Fill entries in last column as 2. There will always be
    // two elements in AP with last number of set as second
    // element in AP
    for (int i = 0; i < n; i++)
        L[i][n-1] = 2;
 
    // Consider every element as second element of AP
    for (int j=n-2; j>=1; j--)
    {
        // Search for i and k for j
        int i = j-1, k = j+1;
        while (i >= 0 && k <= n-1)
        {
           if (set[i] + set[k] < 2*set[j])
               k++;
 
           // Before changing i, set L[i][j] as 2
           else if (set[i] + set[k] > 2*set[j])
           {   L[i][j] = 2, i--;   }
 
           else
           {
               // Found i and k for j, LLAP with i and j as first two
               // elements is equal to LLAP with j and k as first two
               // elements plus 1. L[j][k] must have been filled
               // before as we run the loop from right side
               L[i][j] = L[j][k] + 1;
 
               // Update overall LLAP, if needed
               llap = max(llap, L[i][j]);
 
               // Change i and k to fill more L[i][j] values for
               // current j
               i--; k++;
           }
        }
 
        // If the loop was stopped due to k becoming more than
        // n-1, set the remaining entities in column j as 2
        while (i >= 0)
        {
            L[i][j] = 2;
            i--;
        }
    }
    return llap;
}
 
/* Driver program to test above function*/
int main()
{
    int set1[] = {1, 7, 10, 13, 14, 19};
    int n1 = sizeof(set1)/sizeof(set1[0]);
    cout <<   lenghtOfLongestAP(set1, n1) << endl;
 
    int set2[] = {1, 7, 10, 15, 27, 29};
    int n2 = sizeof(set2)/sizeof(set2[0]);
    cout <<   lenghtOfLongestAP(set2, n2) << endl;
 
    int set3[] = {2, 4, 6, 8, 10};
    int n3 = sizeof(set3)/sizeof(set3[0]);
    cout <<   lenghtOfLongestAP(set3, n3) << endl;
 
    return 0;
}


Java




// Java program to find Length of the
// Longest AP (llap) in a given sorted set.
// The code strictly implements the
// algorithm provided in the reference.
import java.io.*;
 
class GFG
{
    // Returns length of the longest
    // AP subset in a given set
    static int lenghtOfLongestAP(int set[], int n)
    {
        if (n <= 2) return n;
     
        // Create a table and initialize all
        // values as 2. The value ofL[i][j] stores
        // LLAP with set[i] and set[j] as first two
        // elements of AP. Only valid entries are
        // the entries where j>i
        int L[][] = new int[n][n];
         
         // Initialize the result
        int llap = 2;
     
        // Fill entries in last column as 2.
        // There will always be two elements in
        // AP with last number of set as second
        // element in AP
        for (int i = 0; i < n; i++)
            L[i][n - 1] = 2;
     
        // Consider every element as second element of AP
        for (int j = n - 2; j >= 1; j--)
        {
            // Search for i and k for j
            int i = j -1 , k = j + 1;
            while (i >= 0 && k <= n - 1)
            {
            if (set[i] + set[k] < 2 * set[j])
                k++;
     
            // Before changing i, set L[i][j] as 2
            else if (set[i] + set[k] > 2 * set[j])
            {
                L[i][j] = 2; i--;
                 
            }
     
            else
            {
                // Found i and k for j, LLAP with i and j as first two
                // elements is equal to LLAP with j and k as first two
                // elements plus 1. L[j][k] must have been filled
                // before as we run the loop from right side
                L[i][j] = L[j][k] + 1;
     
                // Update overall LLAP, if needed
                llap = Math.max(llap, L[i][j]);
     
                // Change i and k to fill
                // more L[i][j] values for current j
                i--; k++;
            }
            }
     
            // If the loop was stopped due
            // to k becoming more than
            // n-1, set the remaining
            // entities in column j as 2
            while (i >= 0)
            {
                L[i][j] = 2;
                i--;
            }
        }
        return llap;
    }
     
    // Driver program
    public static void main (String[] args)
    {
        int set1[] = {1, 7, 10, 13, 14, 19};
        int n1 = set1.length;
        System.out.println ( lenghtOfLongestAP(set1, n1));
     
        int set2[] = {1, 7, 10, 15, 27, 29};
        int n2 = set2.length;
        System.out.println(lenghtOfLongestAP(set2, n2));
     
        int set3[] = {2, 4, 6, 8, 10};
        int n3 = set3.length;
        System.out.println(lenghtOfLongestAP(set3, n3)) ;
     
     
    }
}
 
// This code is contributed by vt_m


C#




// C# program to find Length of the
// Longest AP (llap) in a given sorted set.
// The code strictly implements the
// algorithm provided in the reference.
using System;
 
class GFG
{
// Returns length of the longest
// AP subset in a given set
static int lenghtOfLongestAP(int []set,
                             int n)
{
    if (n <= 2) return n;
 
    // Create a table and initialize
    // all values as 2. The value of
    // L[i][j] stores LLAP with set[i] 
    // and set[j] as first two elements
    // of AP. Only valid entries are
    // the entries where j>i
    int [,]L = new int[n, n];
     
    // Initialize the result
    int llap = 2;
 
    // Fill entries in last column as 2.
    // There will always be two elements
    // in AP with last number of set as
    // second element in AP
    for (int i = 0; i < n; i++)
        L[i, n - 1] = 2;
 
    // Consider every element as
    // second element of AP
    for (int j = n - 2; j >= 1; j--)
    {
        // Search for i and k for j
        int i = j - 1 , k = j + 1;
        while (i >= 0 && k <= n - 1)
        {
        if (set[i] + set[k] < 2 * set[j])
            k++;
 
        // Before changing i, set L[i][j] as 2
        else if (set[i] + set[k] > 2 * set[j])
        {
            L[i, j] = 2; i--;
             
        }
 
        else
        {
            // Found i and k for j, LLAP with
            // i and j as first two elements
            // is equal to LLAP with j and k
            // as first two elements plus 1.
            // L[j][k] must have been filled
            // before as we run the loop from
            // right side
            L[i, j] = L[j, k] + 1;
 
            // Update overall LLAP, if needed
            llap = Math.Max(llap, L[i, j]);
 
            // Change i and k to fill
            // more L[i][j] values for current j
            i--; k++;
        }
        }
 
        // If the loop was stopped due
        // to k becoming more than
        // n-1, set the remaining
        // entities in column j as 2
        while (i >= 0)
        {
            L[i, j] = 2;
            i--;
        }
    }
    return llap;
}
 
// Driver Code
static public void Main ()
{
    int []set1 = {1, 7, 10, 13, 14, 19};
    int n1 = set1.Length;
    Console.WriteLine(lenghtOfLongestAP(set1, n1));
 
    int []set2 = {1, 7, 10, 15, 27, 29};
    int n2 = set2.Length;
    Console.WriteLine(lenghtOfLongestAP(set2, n2));
 
    int []set3 = {2, 4, 6, 8, 10};
    int n3 = set3.Length;
    Console.WriteLine(lenghtOfLongestAP(set3, n3)) ;
}
}
 
// This code is contributed by Sach_Code


Javascript




<script>
// Javascript program to find Length of the
// Longest AP (llap) in a given sorted set.
// The code strictly implements the
// algorithm provided in the reference.
     
    // Returns length of the longest
    // AP subset in a given set
    function lenghtOfLongestAP(set,n)
    {
        if (n <= 2)
            return n;
         
        // Create a table and initialize all
        // values as 2. The value ofL[i][j] stores
        // LLAP with set[i] and set[j] as first two
        // elements of AP. Only valid entries are
        // the entries where j>i
        let L=new Array(n);
        for(let i=0;i<n;i++)
        {
            L[i]=new Array(n);
        }
         
        // Initialize the result
        let llap = 2;
         
        // Fill entries in last column as 2.
        // There will always be two elements in
        // AP with last number of set as second
        // element in AP
        for (let i = 0; i < n; i++)
        {
            L[i][n - 1] = 2;
        }
        // Consider every element as second element of AP
        for (let j = n - 2; j >= 1; j--)
        {
            // Search for i and k for j
            let i = j -1 , k = j + 1;
            while (i >= 0 && k <= n - 1)
            {
                if (set[i] + set[k] < 2 * set[j])
                    k++;
          
                // Before changing i, set L[i][j] as 2
                else if (set[i] + set[k] > 2 * set[j])
                {
                    L[i][j] = 2; i--;
                      
                }
          
                else
                {
                    // Found i and k for j, LLAP with i and j as first two
                    // elements is equal to LLAP with j and k as first two
                    // elements plus 1. L[j][k] must have been filled
                    // before as we run the loop from right side
                    L[i][j] = L[j][k] + 1;
          
                    // Update overall LLAP, if needed
                    llap = Math.max(llap, L[i][j]);
          
                    // Change i and k to fill
                    // more L[i][j] values for current j
                    i--; k++;
                }
            }
            // If the loop was stopped due
            // to k becoming more than
            // n-1, set the remaining
            // entities in column j as 2
            while (i >= 0)
            {
                L[i][j] = 2;
                i--;
            }
        }
        return llap;
    }
     
    // Driver program
    let set1=[1, 7, 10, 13, 14, 19];
    let n1 = set1.length;
    document.write( lenghtOfLongestAP(set1, n1)+"<br>");
     
    let set2=[1, 7, 10, 15, 27, 29];
    let n2 = set2.length;
    document.write( lenghtOfLongestAP(set2, n2)+"<br>");
     
    let set3=[2, 4, 6, 8, 10];
    let n3 = set3.length;
    document.write( lenghtOfLongestAP(set3, n3)+"<br>");
     
     
    // This code is contributed by avanitrachhadiya2155
     
</script>


PHP




<?php
// PHP program to find Length of the
// Longest AP (llap) in a given sorted set.
 
// The code strictly implements the
// algorithm provided in the reference.
 
// Returns length of the longest AP
// subset in a given set
function lenghtOfLongestAP($set, $n)
{
    if ($n <= 2)
        return $n;
 
    // Create a table and initialize all
    // values as 2. The value of L[i][j]
    // stores LLAP with set[i] and set[j]
    // as first two elements of AP. Only
    // valid entries are the entries where j>i
    $L[$n][$n] = array(array());
    $llap = 2; // Initialize the result
 
    // Fill entries in last column as 2.
    // There will always be two elements
    // in AP with last number of set as
    // second element in AP
    for ($i = 0; $i < $n; $i++)
        $L[$i][$n - 1] = 2;
 
    // Consider every element as
    // second element of AP
    for ($j = $n - 2; $j >= 1; $j--)
    {
        // Search for i and k for j
        $i = $j - 1;
        $k = $j + 1;
        while ($i >= 0 && $k <= $n - 1)
        {
        if ($set[$i] + $set[$k] < 2 * $set[$j])
            $k++;
 
        // Before changing i, set L[i][j] as 2
        else if ($set[$i] + $set[$k] > 2 * $set[$j])
        {
            $L[$i][$j] = 2;
            $i--; }
 
        else
        {
            // Found i and k for j, LLAP with
            // i and j as first two elements
            // is equal to LLAP with j and k
            // as first two elements plus 1.
            // L[j][k] must have been filled
            // before as we run the loop from
            // right side
            $L[$i][$j] = $L[$j][$k] + 1;
 
            // Update overall LLAP, if needed
            $llap = max($llap, $L[$i][$j]);
 
            // Change i and k to fill more
            // L[i][j] values for current j
            $i--;
            $k++;
        }
        }
 
        // If the loop was stopped due to k
        // becoming more than n-1, set the
        // remaining entities in column j as 2
        while ($i >= 0)
        {
            $L[$i][$j] = 2;
            $i--;
        }
    }
    return $llap;
}
 
// Driver Code
$set1 = array(1, 7, 10, 13, 14, 19);
$n1 = sizeof($set1);
echo lenghtOfLongestAP($set1, $n1),"\n";
 
$set2 = array(1, 7, 10, 15, 27, 29);
$n2 = sizeof($set2);
echo lenghtOfLongestAP($set2, $n2),"\n";
 
$set3 = array(2, 4, 6, 8, 10);
$n3 = sizeof($set3);
echo lenghtOfLongestAP($set3, $n3),"\n";
 
// This code is contributed by Sach_Code
?>


Python3




# Python 3 program to find Length of the
# Longest AP (llap) in a given sorted set.
# The code strictly implements the algorithm
# provided in the reference
 
# Returns length of the longest AP
# subset in a given set
def lenghtOfLongestAP(set, n):
 
    if (n <= 2):
        return n
 
    # Create a table and initialize all
    # values as 2. The value of L[i][j]
    # stores LLAP with set[i] and set[j]
    # as first two elements of AP. Only
    # valid entries are the entries where j>i
    L = [[0 for x in range(n)]
            for y in range(n)]
    llap = 2 # Initialize the result
 
    # Fill entries in last column as 2.
    # There will always be two elements
    # in AP with last number of set as
    # second element in AP
    for i in range(n):
        L[i][n - 1] = 2
 
    # Consider every element as second
    # element of AP
    for j in range(n - 2, 0, -1):
 
        # Search for i and k for j
        i = j - 1
        k = j + 1
        while(i >= 0 and k <= n - 1):
 
            if (set[i] + set[k] < 2 * set[j]):
                k += 1
 
            # Before changing i, set L[i][j] as 2
            elif (set[i] + set[k] > 2 * set[j]):
                L[i][j] = 2
                i -= 1
 
            else:
 
                # Found i and k for j, LLAP with i and j
                # as first two elements are equal to LLAP
                # with j and k as first two elements plus 1.
                # L[j][k] must have been filled before as
                # we run the loop from right side
                L[i][j] = L[j][k] + 1
 
                # Update overall LLAP, if needed
                llap = max(llap, L[i][j])
 
                # Change i and k to fill more L[i][j]
                # values for current j
                i -= 1
                k += 1
 
                # If the loop was stopped due to k
                # becoming more than n-1, set the
                # remaining entities in column j as 2
                while (i >= 0):
                    L[i][j] = 2
                    i -= 1
    return llap
 
# Driver Code
if __name__ == "__main__":
     
    set1 = [1, 7, 10, 13, 14, 19]
    n1 = len(set1)
    print(lenghtOfLongestAP(set1, n1))
 
    set2 = [1, 7, 10, 15, 27, 29]
    n2 = len(set2)
    print(lenghtOfLongestAP(set2, n2))
 
    set3 = [2, 4, 6, 8, 10]
    n3 = len(set3)
    print(lenghtOfLongestAP(set3, n3))
 
# This code is contributed by ita_c


Output

4
3
5

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



Last Updated : 07 Mar, 2024
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads