You are given an array of integers, you need to find the length of the longest increasing sub-sequence.

There can be 4 approaches for solving the problem.

**1) Brute force:**

In this approach, we try to find all increasing subsequences and then returning the maximum length of longest increasing subsequence. In order to do this, we make use of a recursive function which returns the length of the LIS possible from the current element onwards.

Time Complexity:

Space Complexity:

**2) Dynamic Programming**

This approach is relying on the fact that LIS up to ith index is independent of the later (n-i+1) elements. Also, the LIS up to (i+1)th element can be calculated by checking the LIS obtained from index 0 to i.

Dynamic Programming approach

Time Complexity:

Space Complexity:

**3) Using Binary Search**

The elements are stored in the increasing order in the DP array where the index is determined using binary search. The length of the array gives the length of the LIS.

Time Complexity:

Space Complexity:

Please refer Construction of Longest Increasing Subsequence (N log N) for details.

**4) Using Segment Tree**

The elements are first sorted in increasing order while retaining their original indices. For strictly increasing LIS, for equal elements, the element with a higher index gets an early spot than the lower. This can be stored in an array of pair.

Now, they are populated in the segment tree. According to their position in their sorted array, they are filled up in the segment tree in the leaves corresponding to their original indices.

Initially, the segment tree was initialised with zeroes. Now, let us assume we have processed ith element in the sorted array. At the (i+1)th iteration, let the original position of the value be j.

Then, it will fill up the jth leaf in the segment tree whose value will be the maximum value of the leaves between 0 to (j-1) +1.

(Length of the LIS formed by the elements lesser than it in the sub array preceding it and +1 for its inclusion)

**Arr[] = {5, 1, 3, 9} Indices : {0, 1, 2, 3}**

**Sorted_Arr[] = {1, 3, 5, 9} Original_Indices : {1, 2, 0, 3} Indices : {0, 1, 2, 3}**

`// Finding the Longest Increasing Subsequence using ` `// Segment Tree ` `#include <bits/stdc++.h> ` `using` `namespace` `std; ` ` ` `// function to compare two pairs ` `int` `compare(pair<` `int` `, ` `int` `> p1, pair<` `int` `, ` `int` `> p2) ` `{ ` ` ` `/* For same values, element with the higher ` ` ` `index appear earlier in the sorted array. ` ` ` `This is for strictly increasing subsequence. ` ` ` `For increasing subsequence, the lower index ` ` ` `appears earlier in the sorted array. */` ` ` `if` `(p1.first == p2.first) ` ` ` `return` `p1.second > p2.second; ` ` ` ` ` `// Sorting the array according to their values. ` ` ` `return` `p1.first < p2.first; ` `} ` ` ` `// Building the entire Segment tree, the root of which ` `// contains the length of the LIS ` `void` `buildTree(` `int` `* tree, ` `int` `pos, ` `int` `low, ` `int` `high, ` ` ` `int` `index, ` `int` `value) ` `{ ` ` ` `// index is the original index of current element ` ` ` `// If the index is not present in the given range, ` ` ` `// then simply return ` ` ` `if` `(index < low || index > high) ` ` ` `return` `; ` ` ` ` ` `// If low == high then the current position should ` ` ` `// be updated to the value ` ` ` `if` `(low == high) { ` ` ` `tree[pos] = value; ` ` ` `return` `; ` ` ` `} ` ` ` ` ` `int` `mid = (high + low) / 2; ` ` ` ` ` `// Recursively call the function on the ` ` ` `// child nodes ` ` ` `buildTree(tree, 2 * pos + 1, low, mid, index, value); ` ` ` `buildTree(tree, 2 * pos + 2, mid + 1, high, index, value); ` ` ` ` ` `// Assign the current position the max of the 2 child ` ` ` `// nodes ` ` ` `tree[pos] = max(tree[2 * pos + 1], tree[2 * pos + 2]); ` `} ` ` ` `// Function to query the Segment tree and return the ` `// value for a given range ` `int` `findMax(` `int` `* tree, ` `int` `pos, ` `int` `low, ` `int` `high, ` ` ` `int` `start, ` `int` `end) ` `{ ` ` ` `// Query: Same as the query function of Segment tree ` ` ` `// If the current range is totally inside the query ` ` ` `// range, return the value of current position ` ` ` `if` `(low >= start && high <= end) ` ` ` `return` `tree[pos]; ` ` ` ` ` `// If it is out of bound, return the minimum which ` ` ` `// would be 0 in this case ` ` ` `if` `(start > high || end < low) ` ` ` `return` `0; ` ` ` ` ` `// Partial overlap ` ` ` `int` `mid = (high + low) / 2; ` ` ` ` ` `// Call findMax on child nodes recursively and ` ` ` `// return the maximum of the two ` ` ` `return` `max(findMax(tree, 2 * pos + 1, low, mid, ` ` ` `start, end), ` ` ` `findMax(tree, 2 * pos + 2, mid + 1, ` ` ` `high, start, end)); ` `} ` ` ` `int` `findLIS(` `int` `arr[], ` `int` `n) ` `{ ` ` ` `// The array of pairs stores the integers and ` ` ` `// indices in p[i] ` ` ` `pair<` `int` `, ` `int` `> p[n]; ` ` ` `for` `(` `int` `i = 0; i < n; i++) { ` ` ` `p[i].first = arr[i]; ` ` ` `p[i].second = i; ` ` ` `} ` ` ` ` ` `// Sorting the array in increasing order ` ` ` `// of the elements ` ` ` `sort(p, p + n, compare); ` ` ` ` ` `// Calculating the length of the segment-tree ` ` ` `int` `len = ` `pow` `(2, (` `int` `)(` `ceil` `(` `sqrt` `(n))) + 1) - 1; ` ` ` `int` `tree[len]; ` ` ` ` ` `// Initializing the tree with zeroes ` ` ` `memset` `(tree, 0, ` `sizeof` `(tree)); ` ` ` ` ` `// Building the segment-tree, the root node of ` ` ` `// which contains the length of LIS for the n ` ` ` `// elements ` ` ` `for` `(` `int` `i = 0; i < n; i++) { ` ` ` `buildTree(tree, 0, 0, n - 1, p[i].second, ` ` ` `findMax(tree, 0, 0, n - 1, 0, p[i].second) + 1); ` ` ` `} ` ` ` ` ` `return` `tree[0]; ` `} ` ` ` `// Driver code ` `int` `main() ` `{ ` ` ` `int` `arr[] = { 10, 22, 9, 33, 21, 50, 41, 60 }; ` ` ` `int` `n = ` `sizeof` `(arr) / ` `sizeof` `(arr[0]); ` ` ` `cout << ` `"Length of the LIS: "` `<< findLIS(arr, n); ` ` ` `return` `0; ` `} ` |

*chevron_right*

*filter_none*

Length of the LIS: 5

**Time Complexity:
Space Complexity: **

This article is contributed by **Pritam Pathak**. 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 write comments if you find anything incorrect, or you want to share more information about the topic discussed above.

Attention reader! Don’t stop learning now. Get hold of all the important CS Theory concepts for SDE interviews with the CS Theory Course at a student-friendly price and become industry ready.

## Recommended Posts:

- Construction of Longest Increasing Subsequence(LIS) and printing LIS sequence
- Weighted Job Scheduling | Set 2 (Using LIS)
- Variations of LIS | DP-21
- Longest Common Increasing Subsequence (LCS + LIS)
- Size of array after repeated deletion of LIS
- Minimum concatenation required to get strictly LIS for array with repetitive elements | Set-2
- Overview of Data Structures | Set 3 (Graph, Trie, Segment Tree and Suffix Tree)
- Build a segment tree for N-ary rooted tree
- Cartesian tree from inorder traversal | Segment Tree
- Euler Tour | Subtree Sum using Segment Tree
- Counting inversions in an array using segment tree
- Queries for elements greater than K in the given index range using Segment Tree
- Range Sum and Update in Array : Segment Tree using Stack
- Queries for elements having values within the range A to B in the given index range using Segment Tree
- Queries for the count of even digit sum elements in the given range using Segment Tree.
- Queries for greatest pair sum in the given index range using Segment Tree
- Maximum of all subarrays of size K using Segment Tree
- Segment Tree | Set 1 (Sum of given range)
- Segment Tree | Set 2 (Range Minimum Query)
- Lazy Propagation in Segment Tree