Longest Increasing Subsequence:
public int Lis(int[] nums,int index,int prev){
if(index==nums.length){
return 0;
}
int take=0;
int notTake=0;
if(prev==-1 || nums[index]>nums[prev]){
take=Lis(nums,index+1,index)+1;
}
notTake=Lis(nums,index+1,prev);
return Math.max(take,notTake);
} Time: O(2^n) Space: O(n). wefwefwe
since there are recuring sub problems we store the subproblems in the dp matrix, with index and prev as it's co-ordinate.
class Solution {
int[][] dp;
public int lengthOfLIS(int[] nums) {
int n=nums.length;
dp=new int[n+1][n+1];
return Lis(nums,0,-1);
}
public int Lis(int[] nums,int index,int prev){
if(index==nums.length) {
return 0;
}
int take=0;
int notTake=0;
if(prev==-1 || nums[index]>nums[prev]){
if(dp[index+1][index+1]==0) {
dp[index+1][index+1]=Lis(nums,index+1,index);
}
take=dp[index+1][index+1]+1;
}
// if the subproblems doesn't exist, then fint it's value
if(dp[index+1][prev+1]==0){
dp[index+1][prev+1]=Lis(nums,index+1,prev);
}
notTake=dp[index+1][prev+1];
return Math.max(take,notTake);
}
}Time: O(n^2) Space: n*n (dp matrix) + n(recursive stack)
Step to convert memoization to tabulation
1. write the base case
2. write the changing parameters (in this case index and prev)
Iterate index from n-1 --> 0 and prev from index-1 --> -1
3. copy the recurrence
//recurrence
if(prev==-1 || nums[index]>nums[prev]){
take=Lis(nums,index+1,index)+1;
}
notTake=Lis(nums,index+1,prev);Just change the Lis(index+1,prev) to dp[index+1][prev+1]
the +1 in the second co-ordinate int the dp is due to the fact the prev can be -1 but index can't so we shift the coordinate by 1.
class Solution {
public int lengthOfLIS(int[] nums) {
int n=nums.length;
int[][] dp=new int[n+1][n+1];
for(int index=n-1;index>-1;index--){
for(int prev=index-1;prev>=-1;prev--){
int take=0;
int notTake=0;
if(prev==-1 || nums[index]>nums[prev]){
take=dp[index+1][index+1]+1;
}
notTake=dp[index+1][prev+1];
dp[index][prev+1]=Math.max(take,notTake);
}
}
return dp[0][0];
}
}Time: O(n^2) Space: (n*n)
In the above code we can see that at every iteration we are dealing with index+1 and index we can space optimise it by using two array instead of matrix and can convert dp[index+1][somethinng] to next[something] and dp[index][something] to curr[something]
class Solution {
public int lengthOfLIS(int[] nums) {
int n=nums.length;
int[] next=new int[n+1];
int[] curr=new int[n+1];
for(int index=n-1;index>-1;index--){
for(int prev=index-1;prev>=-1;prev--){
int take=0;
int notTake=0;
if(prev==-1 || nums[index]>nums[prev]){
take=next[index+1]+1;
}
notTake=next[prev+1];
curr[prev+1]=Math.max(take,notTake);
}
next=curr;
}
return curr[0];
}
}