# Python program for Longest Increasing Subsequence

The Longest Increasing Subsequence (LIS) problem is to find the length of the longest subsequence of a given sequence such that all elements of the subsequence are sorted in increasing order. For example, the length of LIS for {10, 22, 9, 33, 21, 50, 41, 60, 80} is 6 and LIS is {10, 22, 33, 50, 60, 80}. More Examples:

Input : arr[] = {3, 10, 2, 1, 20} Output : Length of LIS = 3 The longest increasing subsequence is 3, 10, 20 Input : arr[] = {3, 2} Output : Length of LIS = 1 The longest increasing subsequences are {3} and {2} Input : arr[] = {50, 3, 10, 7, 40, 80} Output : Length of LIS = 4 The longest increasing subsequence is {3, 7, 40, 80}

**Optimal Substructure:** Let arr[0..n-1] be the input array and L(i) be the length of the LIS ending at index i such that arr[i] is the last element of the LIS. Then, L(i) can be recursively written as: L(i) = 1 + max( L(j) ) where 0 < j < i and arr[j] < arr[i]; or L(i) = 1, if no such j exists. To find the LIS for a given array, we need to return max(L(i)) where 0 < i < n. Thus, we see the LIS problem satisfies the optimal substructure property as the main problem can be solved using solutions to subproblems. Following is a simple recursive implementation of the LIS problem. It follows the recursive structure discussed above.

## Python

`# A naive Python implementation of LIS problem` `""" To make use of recursive calls, this function must ` `return` ` ` `two things:` ` ` `1` `) Length of LIS ending with element arr[n` `-` `1` `]. We use` ` ` `max_ending_here ` `for` `this purpose` ` ` `2` `) Overall maximum as the LIS may end with an element` ` ` `before arr[n` `-` `1` `] max_ref ` `is` `used this purpose.` ` ` `The value of LIS of full array of size n ` `is` `stored` ` ` `in` `*` `max_ref which ` `is` `our final result """` `# global variable to store the maximum` `global` `maximum` `def` `_lis(arr, n ):` ` ` `# to allow the access of global variable` ` ` `global` `maximum` ` ` `# Base Case` ` ` `if` `n ` `=` `=` `1` `:` ` ` `return` `1` ` ` `# maxEndingHere is the length of LIS ending with arr[n-1]` ` ` `maxEndingHere ` `=` `1` ` ` `"""Recursively get ` `all` `LIS ending with arr[` `0` `], arr[` `1` `]..arr[n` `-` `2` `]` ` ` `IF arr[n` `-` `1` `] ` `is` `smaller than arr[n` `-` `1` `], ` `and` `max` `ending with` ` ` `arr[n` `-` `1` `] needs to be updated, then update it"""` ` ` `for` `i ` `in` `xrange` `(` `1` `, n):` ` ` `res ` `=` `_lis(arr, i)` ` ` `if` `arr[i` `-` `1` `] < arr[n` `-` `1` `] ` `and` `res ` `+` `1` `> maxEndingHere:` ` ` `maxEndingHere ` `=` `res ` `+` `1` ` ` `# Compare maxEndingHere with overall maximum. And` ` ` `# update the overall maximum if needed` ` ` `maximum ` `=` `max` `(maximum, maxEndingHere)` ` ` `return` `maxEndingHere` `def` `lis(arr):` ` ` `# to allow the access of global variable` ` ` `global` `maximum` ` ` `# length of arr` ` ` `n ` `=` `len` `(arr)` ` ` `# maximum variable holds the result` ` ` `maximum ` `=` `1` ` ` `# The function _lis() stores its result in maximum` ` ` `_lis(arr, n)` ` ` `return` `maximum` `# Driver program to test the above function` `arr ` `=` `[` `10` `, ` `22` `, ` `9` `, ` `33` `, ` `21` `, ` `50` `, ` `41` `, ` `60` `]` `n ` `=` `len` `(arr)` `print` `"Length of lis ` `is` `", lis(arr)` `# This code is contributed by NIKHIL KUMAR SINGH` |

**Output:**

Length of lis is 5

**Time Complexity**: O(2^{n})

**Auxiliary Space**: O(1)

**Overlapping Subproblems:** Considering the above implementation, following is recursion tree for an array of size 4. lis(n) gives us the length of LIS for arr[].

lis(4) / | lis(3) lis(2) lis(1) / / lis(2) lis(1) lis(1) / lis(1)

We can see that there are many subproblems which are solved again and again. So this problem has Overlapping Substructure property and recomputation of same subproblems can be avoided by either using Memoization or Tabulation. Following is a tabluated implementation for the LIS problem.

## Python

`# Dynamic programming Python implementation of LIS problem` `# lis returns length of the longest increasing subsequence` `# in arr of size n` `def` `lis(arr):` ` ` `n ` `=` `len` `(arr)` ` ` `# Declare the list (array) for LIS and initialize LIS` ` ` `# values for all indexes` ` ` `lis ` `=` `[` `1` `]` `*` `n` ` ` `# Compute optimized LIS values in bottom up manner` ` ` `for` `i ` `in` `range` `(` `1` `, n):` ` ` `for` `j ` `in` `range` `(` `0` `, i):` ` ` `if` `arr[i] > arr[j] ` `and` `lis[i]< lis[j] ` `+` `1` `:` ` ` `lis[i] ` `=` `lis[j]` `+` `1` ` ` `# Initialize maximum to 0 to get the maximum of all` ` ` `# LIS` ` ` `maximum ` `=` `0` ` ` `# Pick maximum of all LIS values` ` ` `for` `i ` `in` `range` `(n):` ` ` `maximum ` `=` `max` `(maximum, lis[i])` ` ` `return` `maximum` `# end of lis function` `# Driver program to test above function` `arr ` `=` `[` `10` `, ` `22` `, ` `9` `, ` `33` `, ` `21` `, ` `50` `, ` `41` `, ` `60` `]` `print` `"Length of lis ` `is` `", lis(arr)` `# This code is contributed by Nikhil Kumar Singh` |

**Output:**

Length of lis is 5

**Time Complexity**: O(n^{2})

**Auxiliary space**: O(n)

Please refer complete article on Dynamic Programming | Set 3 (Longest Increasing Subsequence) for more details!