longest-increasing-subsequence
The Longest Increasing Subsequence (LIS) problem is a classic problem where we are given an array of integers, and our task is to find the length of the longest subsequence that is strictly increasing.
## Problem Statement
Given an integer array nums, return the length of the longest strictly increasing subsequence.
Example 1:
Input: nums = [10,9,2,5,3,7,101,18]
Output: 4
Explanation: The longest increasing subsequence is [2,3,7,101], therefore the length is 4.
Example 2:
Input: nums = [0,1,0,3,2,3]
Output: 4
Example 3:
Input: nums = [7,7,7,7,7,7,7]
Output: 1
Approach
We will solve this problem using three approaches:
1. Recursive Approach
The recursive approach is the brute-force solution. For each index, we consider two options:
Include the current element in the subsequence if it exceeds the previous element.
Exclude the current element from the subsequence.
We then find the maximum length of the subsequence formed by including or excluding the element.
Code - Recursive Solution
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
if len(nums) == 1:
return 1
def dfs(idx , prev):
if idx == len(nums):
return 0
include =0
if prev == -1 or nums[idx] > nums[prev]:
include = dfs(idx+1,idx)+1
exclude = dfs(idx+1,prev)
return max(include,exclude)
return dfs(0,-1)
2. Memoization Dynamic Programming (DP)
In this approach, We have used a dictionary for the same intuition of recursion to avoid re-calculation. Although it is not an optimized solution.
Code - Memoization DP Solution
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
def dfs(idx , prev,memo):
if len(nums) == 1:
return 1
if idx == len(nums):
return 0
if (idx,prev) in memo:
return memo[(idx,prev)]
include =0
if prev == -1 or nums[idx] > nums[prev]:
include = dfs(idx+1,idx,memo)+1
exclude = dfs(idx+1,prev,memo)
memo[(idx,prev)] = max(include,exclude)
return memo[(idx,prev)]
return dfs(0,-1,{})
3. Tabulation Dynamic Programming (DP)
In this approach, we use a table (dp
array) where each entry dp[i]
represents the length of the longest increasing subsequence that ends at index i
.
Initialize
dp[i]
as 1 for all elements (since each element by itself is an increasing subsequence).For each element, check all the previous elements, and if
nums[i] > nums[j]
, updatedp[i]
to the maximum value ofdp[i]
anddp[j] + 1
.
Code - Tabulation DP Solution
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
if len(nums) == 1:
return 1
dp = [1] * len(nums)
for i in range(1,len(nums)):
for j in range(i):
if nums[i] > nums[j]:
dp[i] = max(dp[i], dp[j]+1)
return max(dp)
Time Complexity
Recursive Approach:
O(2^n)
Due to the exponential number of calls (without optimization).Memoization DP:
O(n^2)
since we memoize the results for subproblems, making it more efficient than the naive recursive approach.Tabulation DP:
O(n^2)
wheren
is the length of the input list, as we use two nested loops to fill thedp
array.
Last updated