## Introduction:

In this article, we will explore an efficient algorithm to find the length of the longest increasing subsequence in an array. We'll walk through a step-by-step implementation of the algorithm in C++. Let's dive in!

## Problem Statement:

Given an array of integers, we need to find the length of the longest increasing subsequence. An increasing subsequence is a sequence of array elements in which each element is greater than the previous one. Our goal is to find the longest increasing subsequence and return its length.

## Approach:

To solve this problem efficiently, we can use the Dynamic Programming concept known as the Longest Increasing Subsequence (LIS) algorithm. The main idea behind this algorithm is to build a dynamic array, `tail`, to store the increasing subsequence as we iterate through the given array.

## Algorithm:

- Create an array `tail` of size `n`, where `n` is the length of the input array, to store the increasing subsequence. Initialize `len` to 1, as the minimum length of any subsequence is 1.

- Assign the first element of the input array to `tail[0]`.

- Iterate over the remaining elements of the array from index 1 to `n-1`.

- For each element `a[i]`, compare it with the last element of `tail` (i.e., `tail[len-1]`).

- If `a[i]` is greater than `tail[len-1]`, it can be appended to the current increasing subsequence. Assign `a[i]` to `tail[len]` and increment `len` by 1.

- If `a[i]` is not greater than `tail[len-1]`, find the index `c` using the `ceilIdx` function, which gives the index of the smallest element in `tail` greater than or equal to `a[i]`. Update `tail[c]` with `a[i]`.

- After iterating over all the elements, `len` will hold the length of the longest increasing subsequence.

- Return `len` as the result.

Helper Function: `ceilIdx`

The `ceilIdx` function is a helper function used to find the index of the smallest element in the `tail` array that is greater than or equal to a given `key`. It uses a binary search approach to efficiently search for the index.

## Example:

Let's consider the array: {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15}.

## Algorithm and Cases:

The LIS algorithm consists of three cases that determine how to construct the active lists during iteration:

Case 1: Start a New Active List:

If A[i] is the smallest among all end candidates of the active lists, we start a new active list of length 1.

For example, when A[0] = 0, there are no active lists, so we create one: 0.

Case 2: Clone and Extend:

If A[i] is the largest among all end candidates of the active lists, we clone the largest active list and extend it by A[i].

For example, when A[1] = 8, we clone the existing active list and extend it: 0, 8.

Case 3: Find, Clone, Extend, and Discard:

If A[i] is in between the smallest and largest end elements of the active lists, we find a list with the largest end element that is smaller than A[i]. We then clone and extend this list by A[i]. We discard all other lists of the same length as the modified list.

For example, when A[2] = 4, we clone the list ending at 0, extend it with 4, and discard the list ending at 8: 0, 4.

Let's visualize the step-by-step construction of the active lists using the provided example:

0, 8.

0, 4.

0, 4, 12.

0, 2.

0, 2, 10.

0, 2, 6.

0, 2, 6, 14.

0, 1.

0, 2, 6, 9.

0, 1, 5.

0, 2, 6, 9, 13.

0, 1, 3.

0, 2, 6, 9, 11.

0, 1, 3, 7.

0, 2, 6, 9, 11, 15.

## Code:

```cpp

#include <iostream>

using namespace std;

class Solution {

public:

// Function to find the index of the smallest element in the 'tail' array greater than or equal to 'key'

int ceilIdx(int tail[], int l, int r, int key) {

while (r > l) {

int m = l + (r - l) / 2;

if (tail[m] >= key)

r = m;

else

l = m + 1;

}

return r;

}

// Function to find the length of the longest increasing subsequence

int longestSubsequence(int n, int a[]) {

int tail[n];

int len = 1;

tail[0] = a[0];

for (int i = 1; i < n; i++) {

if (a[i] > tail[len - 1]) {

tail[len] = a[i];

len++;

}

else {

int c = ceilIdx(tail, 0, len - 1, a[i]);

tail[c] = a[i];

}

}

return len;

}

};

int main() {

int n;

cin >> n;

int a[n];

// Taking input for the array elements

for (int i = 0; i < n; i++)

cin >> a[i];

Solution ob;

cout << ob.longestSubsequence(n, a) << endl;

return 0;

}

```

## Conclusion:

In this article, we discussed an efficient approach to finding the length of the longest increasing subsequence in an array using the LIS algorithm. We walked through the step-by-step implementation of the algorithm in C++. By using the dynamic programming concept, we were able to achieve an optimal solution to the problem. I hope you found this article helpful in understanding the concept and implementation.