class Solution {
public:
int recursion(int n,vector<int> &dp){
if(n==0 || n==1) return 1;
if(dp[n]!=-1) return dp[n];
return dp[n]=recursion(n-1,dp)+recursion(n-2,dp);
}
int climbStairs(int n) {
vector<int> dp(n+1,-1);
return recursion(n,dp);
}
};
#include <bits/stdc++.h>
int recursion(int ind,vector<int> &v){
if(ind==0) return 0;
int l=recursion(ind-1,v)+abs(v[ind]-v[ind-1]);
int r=INT_MAX;
if(ind>1) r=recursion(ind-2,v)+abs(v[ind]-v[ind-2]);
return min(l,r);
}
int frogJump(int n, vector<int> &v)
{
return recursion(n-1,v);
}
#include <bits/stdc++.h>
int recursion(int ind,vector<int> &v,vector<int> &dp){
if(ind==0) return 0;
if(dp[ind]!=-1) return dp[ind];
int l=recursion(ind-1,v,dp)+abs(v[ind]-v[ind-1]);
int r=INT_MAX;
if(ind>1) r=recursion(ind-2,v,dp)+abs(v[ind]-v[ind-2]);
return dp[ind]=min(l,r);
}
int frogJump(int n, vector<int> &v)
{
vector<int> dp(n,-1);
return recursion(n-1,v,dp);
}
int frogJump(int n, vector<int> &v)
{
vector<int> dp(n,-1);
dp[0]=0;
for(int i=1;i<n;i++){
int fs=dp[i-1]+abs(v[i]-v[i-1]);
int ss=INT_MAX;
if(i>1)
ss= dp[i-2]+abs(v[i]-v[i-2]);
dp[i]=min(fs,ss);
}
return dp[n-1];
}
int frogJump(int n, vector<int> &v)
{
int prev=0,prev2=0;
for(int i=1;i<n;i++){
int fs=prev+abs(v[i]-v[i-1]);
int ss=INT_MAX;
if(i>1)
ss= prev2+abs(v[i]-v[i-2]);
int curr=min(fs,ss);
prev2=prev;
prev=curr;
}
return prev;
}
int minimizeCost(int n, int k, vector<int> &v){
// Write your code here.
vector<int> dp(n);
dp[0]=0;
for(int i=1;i<n;i++){
int minSteps=INT_MAX;
for(int j=1;j<=k;j++){
if((i-j)>=0){
int steps=dp[i-j]+abs(v[i]-v[i-j]);
minSteps=min(minSteps,steps);
}
}
dp[i]=minSteps;
}
return dp[n-1];
}
class Solution {
public:
bool canCross(vector<int>& stones) {
unordered_map<int, unordered_set<int>> dp;
for(auto position: stones)dp[position]=unordered_set<int>();
dp[0].insert(0);
for(auto position:stones){
for(auto k:dp[position]){
if(k-1>0 && dp.find(position+k-1)!=dp.end())
dp[position+k-1].insert(k-1);
if(dp.find(position+k)!=dp.end())
dp[position+k].insert(k);
if(dp.find(position+k+1)!=dp.end())
dp[position+k+1].insert(k+1);
}
}
return !dp[stones.back()].empty();
}
};
#include <bits/stdc++.h>
int recursion(int ind,vector<int> &dp,vector<int> &nums){
if(ind==0) return nums[ind];
if(ind<0) return 0;
if(dp[ind]!=-1) return dp[ind];
int pick=nums[ind]+recursion(ind-2,dp,nums);
int notPick=0+recursion(ind-1,dp,nums);
return dp[ind]=max(pick,notPick);
}
int maximumNonAdjacentSum(vector<int> &nums){
// Write your code here.
int n=nums.size();
vector<int> dp(n,-1);
return recursion(n-1,dp,nums);
}
int maximumNonAdjacentSum(vector<int> &nums){
// Write your code here.
int n=nums.size();
vector<int> dp(n,-1);
dp[0]=nums[0];
for(int i=1;i<n;i++){
int pick=nums[i];
if(i>1)
pick=nums[i]+dp[i-2];
int nonPick=0+dp[i-1];
dp[i]=max(pick,nonPick);
}
return dp[n-1];
}
int maximumNonAdjacentSum(vector<int> &nums){
// Write your code here.
int n=nums.size();
int prev=nums[0];
int prev2=0;
for(int i=1;i<n;i++){
int pick=nums[i];
if(i>1)
pick=nums[i]+prev2;
int nonPick=0+prev;
int curr=max(pick,nonPick);
prev2=prev;
prev=curr;
}
return prev;
}
class Solution {
public:
int rob(vector<int>& nums) {
int n=nums.size();
vector<int> dp(n,-1);
dp[0]=nums[0];
for(int i=1;i<n;i++){
int pick=nums[i];
if(i>1)
pick=nums[i]+dp[i-2];
int nonPick=0+dp[i-1];
dp[i]=max(pick,nonPick);
}
return dp[n-1];
}
};
#define ll long long int
class Solution {
public:
ll solve(vector<int> &nums){
int n=nums.size();
vector<ll> dp(n,-1);
dp[0]=nums[0]*1LL;
for(int i=1;i<n;i++){
ll pick=nums[i];
if(i>1) pick=nums[i]+dp[i-2];
ll nonPick=0+dp[i-1];
dp[i]=max(pick,nonPick);
}
return dp[n-1];
}
int rob(vector<int>& nums) {
vector<int> nums1,nums2;
int n=nums.size();
if(n==1) return nums[0];
for(int i=0;i<n;i++){
if(i!=0) nums1.push_back(nums[i]);
if(i!=n-1) nums2.push_back(nums[i]);
}
return max(solve(nums1),solve(nums2));
}
};
int recursion(vector<vector<int>>&points,int day,int lastIndex){
if(day==0){
int maxi=0;
for(int i=0;i<3;i++){
if(i!=lastIndex){
maxi=max(maxi,points[day][i]);
}
}
return maxi;
}
int maxi=0;
for(int i=0;i<3;i++){
if(i!=lastIndex){
int pointsToday=points[day][i]+recursion(points,day-1,i);
maxi=max(maxi,pointsToday);
}
}
return maxi;
}
int ninjaTraining(int n, vector<vector<int>> &points)
{
// Write your code here.
vector<vector<int>> dp(n,vector<int>(3,0));
return recursion(points,n-1,4);
}
int recursion(vector<vector<int>>&points,int day,int lastIndex,vector<vector<int>>&dp){
if(day==0){
int maxi=0;
for(int i=0;i<3;i++){
if(i!=lastIndex){
maxi=max(maxi,points[day][i]);
}
}
return maxi;
}
if(dp[day][lastIndex]!=-1) return dp[day][lastIndex];
int maxi=0;
for(int i=0;i<3;i++){
if(i!=lastIndex){
int pointsToday=points[day][i]+recursion(points,day-1,i,dp);
maxi=max(maxi,pointsToday);
}
}
// return maxi;
return dp[day][lastIndex]=maxi;
}
int ninjaTraining(int n, vector<vector<int>> &points)
{
// Write your code here.
vector<vector<int>> dp(n,vector<int>(4,-1));
return recursion(points,n-1,3,dp);
}
int ninjaTraining(int n, vector<vector<int>> &points)
{
// Write your code here.
vector<vector<int>> dp(n,vector<int>(4,-1));
dp[0][0]=max(points[0][1],points[0][2]);
dp[0][1]=max(points[0][0],points[0][2]);
dp[0][2]=max(points[0][0],points[0][1]);
dp[0][3] = max(points[0][1], max(points[0][2], points[0][0]));
for(int day=1;day<n;day++){
for(int lastIndex=0;lastIndex<4;lastIndex++){
dp[day][lastIndex]=0;
int maxi=0;
for(int task=0;task<3;task++){
if(lastIndex!=task){
int pointToday=points[day][task]+dp[day-1][task];
maxi=max(pointToday,maxi);
}
}
dp[day][lastIndex]=maxi;
}
}
return dp[n-1][3];
}
int ninjaTraining(int n, vector<vector<int>> &points)
{
// Write your code here.
vector<int> dp(4,-1);
dp[0]=max(points[0][1],points[0][2]);
dp[1]=max(points[0][0],points[0][2]);
dp[2]=max(points[0][0],points[0][1]);
dp[3]=max(points[0][0],max(points[0][1],points[0][2]));
for(int day=1;day<n;day++){
vector<int> temp(4,-1);
for(int lastIndex=0;lastIndex<4;lastIndex++){
temp[lastIndex]=0;
int maxi=0;
for(int task=0;task<3;task++){
if(lastIndex!=task){
int pointToday=points[day][task]+dp[task];
maxi=max(pointToday,maxi);
}
}
temp[lastIndex]=maxi;
}
dp=temp;
}
return dp[3];
}
class Solution {
public:
int uniquePaths(int m, int n) {
if(m==1 && n==1) return 1;
if(m<0 || n<0) return 0;
int l=uniquePaths(m-1,n);
int r=uniquePaths(m,n-1);
return l+r;
}
};
class Solution {
public:
int recursion(int m,int n ,vector<vector<int>> &dp){
if(m==1 && n==1) return 1;
if(m<0 || n<0) return 0;
if(dp[m][n]!=-1) return dp[m][n];
int l=recursion(m-1,n,dp);
int r=recursion(m,n-1,dp);
return dp[m][n]=l+r;
}
int uniquePaths(int m, int n) {
vector<vector<int>> dp(m+1,vector<int>(n+1,-1));
return recursion(m,n,dp);
}
};
class Solution {
public:
int uniquePaths(int m, int n) {
vector<vector<int>> dp(m,vector<int>(n,0));
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(i==0 && j==0)
dp[i][j]=1;
else
{
int l=0,r=0;
if(i>0) l=dp[i-1][j];
if(j>0) r=dp[i][j-1];
dp[i][j]=l+r;
}
}
}
return dp[m-1][n-1];
}
};
class Solution {
public:
int recursion(int m,int n,vector<vector<int>> &grid,vector<vector<int>>&dp){
if(m==0 && n==0) return grid[m][n];
if(m<0 || n<0) return INT_MAX;
if(dp[m][n]!=-1) return dp[m][n];
int l=recursion(m-1,n,grid,dp);
int r=recursion(m,n-1,grid,dp);
return dp[m][n]=grid[m][n]+min(l,r);
}
int minPathSum(vector<vector<int>>& grid) {
int m=grid.size();
if(m==0) return 0;
int n=grid[0].size();
vector<vector<int>>dp(m,vector<int>(n,-1));
return recursion(m-1,n-1,grid,dp);
}
};
class Solution {
public:
int minPathSum(vector<vector<int>>& grid) {
int m=grid.size();
if(m==0) return 0;
int n=grid[0].size();
vector<vector<int>>dp(m,vector<int>(n,0));
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(i==0 && j==0) dp[i][j]=grid[i][j];
else {
int l=INT_MAX,r=INT_MAX;
if(i>0) l=grid[i][j]+dp[i-1][j];
if(j>0) r=grid[i][j]+dp[i][j-1];
dp[i][j]=min(l,r);
}
}
}
return dp[m-1][n-1];
}
};
class Solution {
public:
int recursion(int m,int n,vector<vector<int>> &dp,vector<vector<int>> &grid){
if(m==0 && n==0) return 1;
if(m<0 || n<0 || grid[m][n]==1) return 0;
int l=0,r=0;
if(dp[m][n]!=-1) return dp[m][n];
if(m>0) l=recursion(m-1,n,dp,grid);
if(n>0) r=recursion(m,n-1,dp,grid);
return dp[m][n]=l+r;
}
int uniquePathsWithObstacles(vector<vector<int>>& grid) {
int m=grid.size();
if(m==0) return 0;
int n=grid[0].size();
if(grid[m-1][n-1]) return 0;
if(grid[0][0]) return 0;
vector<vector<int>> dp(m,vector<int>(n,-1));
return recursion(m-1,n-1,dp,grid);
}
};
class Solution {
public:
int uniquePathsWithObstacles(vector<vector<int>>& grid) {
int m=grid.size();
if(m==0) return 0;
int n=grid[0].size();
if(grid[m-1][n-1]) return 0;
if(grid[0][0]) return 0;
vector<vector<int>> dp(m,vector<int>(n,0));
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(i==0 && j==0) dp[i][j]=1;
else {
if(grid[i][j]==1) dp[i][j]=0;
else {
int l=0,r=0;
if(i>0) l=dp[i-1][j];
if(j>0) r=dp[i][j-1];
dp[i][j]=l+r;
}
}
}
}
return dp[m-1][n-1];
}
};
class Solution {
public:
int recursion(int i,int j,int fi,int fj,vector<vector<int>>&grid,int n,int m,int toVisit,vector<vector<int>> &dp){
if(i==fi && j==fj){
return (toVisit==1)?1:0;
}
if(i<0 || j <0 || i>=m || j >=n ||grid[i][j]==-1) return 0;
// if(dp[i][j]!=-1) return dp[i][j];
grid[i][j]=-1;
int l=0,r=0,u=0,d=0;
if(i>0) l=recursion(i-1,j,fi,fj,grid,n,m,toVisit-1,dp);
if(j>0) r=recursion(i,j-1,fi,fj,grid,n,m,toVisit-1,dp);
if(i<m) u=recursion(i+1,j,fi,fj,grid,n,m,toVisit-1,dp);
if(j<n) d=recursion(i,j+1,fi,fj,grid,n,m,toVisit-1,dp);
grid[i][j]=0;
return r+l+u+d;
}
int uniquePathsIII(vector<vector<int>>& grid) {
int m=grid.size();
if(m==0) return 0;
int n=grid[0].size();
int toVisit = 0;
pair<int,int> start={-1,-1},end={-1,-1};
vector<vector<int>> dp(n,vector<int>(m,-1));
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == 1) {
start = {i, j};
}
if (grid[i][j] == 2) {
end = {i, j};
}
if (grid[i][j] != -1) {
toVisit++;
}
}
}
return recursion(start.first, start.second, end.first, end.second, grid, n, m,toVisit,dp);
}
};
class Solution {
public:
int recursion(vector<vector<int>>& triangle,vector<vector<int>>&dp,int i,int j,int n){
if(i==n-1) return triangle[n-1][j];
int d=recursion(triangle,dp,i+1,j,n);
int dg=recursion(triangle,dp,i+1,j+1,n);
return triangle[i][j]+min(d,dg);
}
int minimumTotal(vector<vector<int>>& triangle) {
int n=triangle.size();
vector<vector<int>> dp(n,vector<int>(n,-1));
return recursion(triangle,dp,0,0,n);
}
};
class Solution {
public:
int recursion(vector<vector<int>>& triangle,vector<vector<int>>&dp,int i,int j,int n){
if(i==n-1) return triangle[n-1][j];
if(dp[i][j]!=-1) return dp[i][j];
int d=recursion(triangle,dp,i+1,j,n);
int dg=recursion(triangle,dp,i+1,j+1,n);
return dp[i][j]=triangle[i][j]+min(d,dg);
}
int minimumTotal(vector<vector<int>>& triangle) {
int n=triangle.size();
vector<vector<int>> dp(n,vector<int>(n,-1));
return recursion(triangle,dp,0,0,n);
}
};
class Solution {
public:
int minimumTotal(vector<vector<int>>& triangle) {
int n=triangle.size();
vector<vector<int>> dp(n,vector<int>(n,0));
for(int j=0;j<n;j++) dp[n-1][j]=triangle[n-1][j];
for(int i=n-2;i>=0;i--){
for(int j=i;j>=0;j--){
int d=dp[i+1][j];
int dg=dp[i+1][j+1];
dp[i][j]=triangle[i][j]+min(d,dg);
}
}
return dp[0][0];
}
};
class Solution {
public:
int recursion(vector<vector<int>> &dp, vector<vector<int>>& mat, int row, int col, int n) {
if (col < 0 || col >= n || row >= n) return 1e9;
if (row == n - 1) return mat[row][col];
if (dp[row][col] != -1) return dp[row][col];
int down = recursion(dp, mat, row + 1, col, n);
int downDiag = recursion(dp, mat, row + 1, col + 1, n);
int upperDiag = recursion(dp, mat, row + 1, col - 1, n);
return dp[row][col] = mat[row][col] + min({down, downDiag, upperDiag});
}
int minFallingPathSum(vector<vector<int>>& mat) {
int n = mat.size();
vector<vector<int>> dp(n, vector<int>(n, -1));
int ans = 1e9;
for (int col = 0; col < n; col++) {
ans = min(ans, recursion(dp, mat, 0, col, n));
}
return ans;
}
};
class Solution {
public:
int recursion(vector<vector<int>> &dp, vector<vector<int>>& mat, int row, int col, int n) {
if (col < 0 || col >= n) return 1e9;
if (row == 0) return mat[row][col];
if (dp[row][col] != -1) return dp[row][col];
int down = recursion(dp, mat, row - 1, col, n);
int downDiag = recursion(dp, mat, row - 1, col - 1, n);
int upperDiag = recursion(dp, mat, row - 1, col + 1, n);
return dp[row][col] = mat[row][col] + min({down, downDiag, upperDiag});
}
int minFallingPathSum(vector<vector<int>>& mat) {
int n = mat.size();
vector<vector<int>> dp(n, vector<int>(n, -1));
int ans = 1e9;
for (int col = 0; col < n; col++) {
ans = min(ans, recursion(dp, mat, n-1, col, n));
}
return ans;
}
};
class Solution {
public:
int minFallingPathSum(vector<vector<int>>& mat) {
int n = mat.size();
vector<vector<int>> dp(n, vector<int>(n, 1e9));
for(int j=0;j<n;j++) dp[0][j]= mat[0][j];
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(i==0) continue;
int down=INT_MAX,downDiag=INT_MAX,upperDiag=INT_MAX;
down=dp[i-1][j];
if(j>0) downDiag=dp[i-1][j-1];
if(j<n-1)upperDiag=dp[i-1][j+1];
dp[i][j]=mat[i][j]+min({down,downDiag,upperDiag});
}
}
int ans = 1e9;
for (int col = 0; col < n; col++) {
ans=min(ans,dp[n-1][col]);
}
return ans;
}
};
//{ Driver Code Starts
#include <bits/stdc++.h>
using namespace std;
// } Driver Code Ends
class Solution {
public:
int recursion(int i,int j1,int j2,int n,int m,vector<vector<int>> &grid){
if(j1<0 || j2<0 || j1>=m || j2>=m) return -1e8;
if(i==n-1){
if(j1==j2) return grid[i][j1];
else return grid[i][j1]+grid[i][j2];
}
int maxi=-1e8;
// there will be 9 ways (+1,0,-1)*3 then writting in the loop;
for(int dj1=-1;dj1<=1;dj1++){
for(int dj2=-1;dj2<=1;dj2++){
int value=0;
if(j1==j2) value=grid[i][j1];
else value=grid[i][j1]+grid[i][j2];
value+=recursion(i+1,j1+dj1,j2+dj2,n,m,grid);
maxi=max(maxi,value);
}
}
return maxi;
}
int solve(int n, int m, vector<vector<int>>& grid) {
// code
return recursion(0,0,m-1,n,m,grid);
}
};
//{ Driver Code Starts.
int main() {
int t;
cin >> t;
while (t--) {
int n, m;
cin >> n >> m;
vector<vector<int>> grid;
for (int i = 0; i < n; i++) {
vector<int> temp;
for (int j = 0; j < m; j++) {
int x;
cin >> x;
temp.push_back(x);
}
grid.push_back(temp);
}
Solution obj;
cout << obj.solve(n, m, grid) << "\n";
}
return 0;
}
// } Driver Code Ends
//{ Driver Code Starts
#include <bits/stdc++.h>
using namespace std;
// } Driver Code Ends
class Solution {
public:
int recursion(int i,int j1,int j2,int n,int m,vector<vector<int>> &grid,vector<vector<vector<int>>>&dp){
if(j1<0 || j2<0 || j1>=m || j2>=m) return -1e8;
if(i==n-1){
if(j1==j2) return grid[i][j1];
else return grid[i][j1]+grid[i][j2];
}
if(dp[i][j1][j2]!=-1) return dp[i][j1][j2];
int maxi=-1e8;
// there will be 9 ways (+1,0,-1)*3 then writting in the loop;
for(int dj1=-1;dj1<=1;dj1++){
for(int dj2=-1;dj2<=1;dj2++){
int value=0;
if(j1==j2) value=grid[i][j1];
else value=grid[i][j1]+grid[i][j2];
value+=recursion(i+1,j1+dj1,j2+dj2,n,m,grid,dp);
maxi=max(maxi,value);
}
}
return dp[i][j1][j2]=maxi;
}
int solve(int n, int m, vector<vector<int>>& grid) {
// code
vector<vector<vector<int>>> dp(n,vector<vector<int>>(m,vector<int>(m,-1)));
return recursion(0,0,m-1,n,m,grid,dp);
}
};
//{ Driver Code Starts.
int main() {
int t;
cin >> t;
while (t--) {
int n, m;
cin >> n >> m;
vector<vector<int>> grid;
for (int i = 0; i < n; i++) {
vector<int> temp;
for (int j = 0; j < m; j++) {
int x;
cin >> x;
temp.push_back(x);
}
grid.push_back(temp);
}
Solution obj;
cout << obj.solve(n, m, grid) << "\n";
}
return 0;
}
// } Driver Code Ends
class Solution {
public:
int recursion(int i,int j1,int j2,int n,int m,vector<vector<int>> &grid,vector<vector<vector<int>>>&dp){
if(j1<0 || j2<0 || j1>=m || j2>=m) return -1e8;
if(i==n-1){
if(j1==j2) return grid[i][j1];
else return grid[i][j1]+grid[i][j2];
}
if(dp[i][j1][j2]!=-1) return dp[i][j1][j2];
int maxi=-1e8;
for(int dj1=-1;dj1<=1;dj1++){
for(int dj2=-1;dj2<=1;dj2++){
int value=0;
if(j1==j2) value=grid[i][j1];
else value=grid[i][j1]+grid[i][j2];
value+=recursion(i+1,j1+dj1,j2+dj2,n,m,grid,dp);
maxi=max(maxi,value);
}
}
return dp[i][j1][j2]=maxi;
}
int solve(int n, int m, vector<vector<int>>& grid) {
vector<vector<vector<int>>> dp(n, vector<vector<int>>(m, vector<int>(m, -1e8)));
for (int j1 = 0; j1 < m; j1++) {
for (int j2 = 0; j2 < m; j2++) {
if (j1 == j2) {
dp[n-1][j1][j2] = grid[n-1][j1];
} else {
dp[n-1][j1][j2] = grid[n-1][j1] + grid[n-1][j2];
}
}
}
for (int i = n - 2; i >= 0; i--) {
for (int j1 = 0; j1 < m; j1++) {
for (int j2 = 0; j2 < m; j2++) {
int maxi = -1e8;
for (int dj1 = -1; dj1 <= 1; dj1++) {
for (int dj2 = -1; dj2 <= 1; dj2++) {
int value = 0;
if (j1 == j2) {
value = grid[i][j1];
} else {
value = grid[i][j1] + grid[i][j2];
}
int newJ1 = j1 + dj1;
int newJ2 = j2 + dj2;
if (newJ1 >= 0 && newJ1 < m && newJ2 >= 0 && newJ2 < m) {
value += dp[i+1][newJ1][newJ2];
} else {
value += -1e8;
}
maxi = max(maxi, value);
}
}
dp[i][j1][j2] = maxi;
}
}
}
return dp[0][0][m-1];
}
};
bool recursion(vector<int> &arr,int ind,int target,vector<vector<int>> &dp){
if(target==0) return true;
if(ind==0) return arr[ind]==target;
if(dp[ind][target]!=-1) return dp[ind][target]==1;
bool notTake=recursion(arr,ind-1,target,dp);
bool take=false;
if(target>=arr[ind]){
take=recursion(arr,ind-1,target-arr[ind],dp);
}
bool ans=(take || notTake);
dp[ind][target]=(ans==true)?1:0;
return dp[ind][target]==1?true:false;
}
bool isSubsetSum(vector<int>arr, int sum){
int n=arr.size();
vector<vector<int>> dp(n,vector<int>(sum+1,-1));
return recursion(arr,n-1,sum,dp);
}
bool isSubsetSum(vector<int>arr, int sum){
int n=arr.size();
vector<vector<int>> dp(n,vector<int>(sum+1,0));
for(int i=0;i<n;i++) dp[i][0]=1;
if(arr[0]<=sum)
dp[0][arr[0]]=1;
for(int i=1;i<n;i++){
for(int j=1;j<=sum;j++){
bool notTake=(dp[i-1][j]==1);
bool take=false;
if(j>=arr[i]){
take=(dp[i-1][j-arr[i]]==1);
}
bool ans=(take || notTake);
dp[i][j]=(ans==true)?1:0;
}
}
return dp[n-1][sum]==1;
}
class Solution {
public:
bool recursion(vector<int> &nums,int sum,int ind,vector<vector<int>> &dp){
if(sum==0) return true;
if(ind<0 || sum<0) return false;
if(ind==0) return sum==nums[0];
if(dp[ind][sum]!=-1) return dp[ind][sum];
bool notTake=recursion(nums,sum,ind-1,dp);
bool take=recursion(nums,sum-nums[ind],ind-1,dp);
bool ans=(take || notTake);
dp[ind][sum]=((ans==true)?1:0);
return dp[ind][sum]==1;
}
bool canPartition(vector<int>& nums) {
int sum=accumulate(begin(nums),end(nums),0);
if(sum&1) return false;
int n=nums.size();
vector<vector<int>> dp(n,vector<int>(sum/2+1,-1));
return recursion(nums,sum/2,n-1,dp);
}
};
bool recursion(vector<vector<int>> &dp,vector<int>&arr,int ind,int target){
if(target==0) return true;
if(ind<0 || target<0) return false;
bool notTake=recursion(dp,arr,ind-1,target);
bool take=false;
if (target >= arr[ind]) {
take = recursion(dp, arr, ind - 1, target - arr[ind]);
}
int ans=(take|| notTake);
dp[ind][target]=(ans==true)?1:0;
return dp[ind][target]==1;
}
int minSubsetSumDifference(vector<int>& arr, int n)
{
int sum=accumulate(begin(arr),end(arr),0LL);
vector<vector<bool>> dp(n,vector<bool>(sum+1,0));
for(int i=0;i<n;i++) dp[i][0]=1;
if(arr[0]<=sum) dp[0][arr[0]]=1;
for(int ind=1;ind<n;ind++){
for(int target=1;target<=sum;target++){
bool notTake=dp[ind-1][target];
bool take=false;
if(arr[ind]<=target) take=dp[ind-1][target-arr[ind]];
dp[ind][target]=(take | notTake);
}
}
// recursion(dp,arr,n-1,sum);
int mini=1e9;
for(int s1=0;s1<=sum/2;s1++){
if(dp[n-1][s1]==1){
mini = min(mini, abs((sum - s1) - s1));
}
}
return mini;
}
int minDifference(int arr[], int n) {
// Your code goes here
int sum=accumulate(arr,arr+n,0);
vector<vector<bool>> dp(n,vector<bool>(sum,0));
for(int i=0;i<n;i++) dp[i][0]=true;
if(arr[0]<=sum) dp[0][arr[0]]=true;
for(int ind=1;ind<n;ind++){
for(int target=1;target<=sum;target++){
bool take=false;
bool notTake=dp[ind-1][target];
if(target>=arr[ind]) take=dp[ind-1][target-arr[ind]];
dp[ind][target]=(take | notTake);
}
}
int mini=1e9;
for(int s1=0;s1<=sum/2;s1++){
if(dp[n-1][s1]){
mini=min(mini,abs((sum-s1)-s1));
}
}
return mini;
}
1.Why if(arr[0] <= sum) dp[0][arr[0]] = true;:
This is initializing the first element of the dp array. It means that if the first element arr[0] is less than or equal to the total sum, then it is possible to form a subset with this sum. This initialization is necessary to handle the base case for dynamic programming when processing subsequent elements.
2.Why if(dp[n-1][s1]) mini = min(mini, abs((sum-s1) - s1));:
Here, dp[n-1][s1] checks whether it’s possible to form a subset with sum s1 using all elements (up to index n-1). If so, you compute the absolute difference between sum - s1 (the sum of the other subset) and s1 and update the minimum difference (mini). The goal is to minimize the difference between the two subset sums.
3.Why use n-1:
n-1 represents the last element in the array arr when using 0-based indexing. The dynamic programming table dp has size n, where dp[i][target] tells if it’s possible to form the sum target using elements from arr[0] to arr[i]. Thus, dp[n-1] checks if it’s possible to form the sum using all elements from the array.
int minSubsetSumDifference(vector<int>& arr, int n) {
int sum = accumulate(arr.begin(), arr.end(), 0);
vector<bool> dp(sum / 2 + 1, false);
dp[0] = true;
for (int num : arr) {
for (int target = sum / 2; target >= num; target--) {
dp[target] = dp[target] || dp[target - num];
}
}
int mini = INT_MAX;
for (int s1 = sum / 2; s1 >= 0; s1--) {
if (dp[s1]) {
mini = min(mini, abs((sum - s1) - s1));
}
}
return mini;
}
class Solution {
public:
bool recursion(vector<int> &nums,int sum,int ind,vector<vector<int>> &dp){
if(sum==0) return true;
if(ind<0 || sum<0) return false;
if(ind==0) return sum==nums[0];
if(dp[ind][sum]!=-1) return dp[ind][sum];
bool notTake=recursion(nums,sum,ind-1,dp);
bool take=recursion(nums,sum-nums[ind],ind-1,dp);
bool ans=(take || notTake);
dp[ind][sum]=((ans==true)?1:0);
return dp[ind][sum]==1;
}
bool canPartition(vector<int>& nums) {
int sum=accumulate(begin(nums),end(nums),0);
if(sum&1) return false;
int n=nums.size();
vector<vector<int>> dp(n,vector<int>(sum/2+1,-1));
return recursion(nums,sum/2,n-1,dp);
}
};
// class Solution {
// public:
// bool recursion(vector<vector<int>> &dp,vector<int> &nums,int k,int ind,int target){
// if(k==0) return true;
// if(ind<0) return false;
// if(dp[ind][target]!=-1) return dp[ind][target]==1;
// if(target==0) {
// bool x=recursion(dp,nums,k-1,ind,target);
// dp[ind][target]=(x==true?1:0);
// return x;
// }
// bool pick=false;
// bool nonPick=recursion(dp,nums,k,ind-1,target);
// if(target>=nums[ind]) pick=recursion(dp,nums,k,ind-1,target-nums[ind]);
// bool ans=(pick || nonPick);
// dp[ind][target]=(ans==true?1:0);
// return ans;
// }
// bool canPartitionKSubsets(vector<int>& nums, int k) {
// int n=nums.size();
// sort(nums.begin(), nums.end(), greater<int>());
// int sum=accumulate(begin(nums),end(nums),0);
// int target=sum/k;
// if (nums[0] > target) return false;
// if(sum % k !=0) return false;
// vector<vector<int>> dp(n,vector<int>(target+1,-1));
// return recursion(dp,nums,k,n-1,target);
// }
// };
class Solution {
public:
bool canPartitionHelper(vector<int>& nums, vector<bool>& used, int target, int k, int start, int currSum) {
if (k == 1) return true;
if (currSum == target)
return canPartitionHelper(nums, used, target, k - 1, 0, 0);
for (int i = start; i < nums.size(); ++i) {
if (!used[i] && currSum + nums[i] <= target) {
used[i] = true;
if (canPartitionHelper(nums, used, target, k, i + 1, currSum + nums[i]))
return true;
used[i] = false;
}
}
return false;
}
bool canPartitionKSubsets(vector<int>& nums, int k) {
int sum = accumulate(nums.begin(), nums.end(), 0);
if (sum % k != 0) return false;
int target = sum / k;
sort(nums.begin(), nums.end(), greater<int>());
if (nums[0] > target) return false;
vector<bool> used(nums.size(), false);
return canPartitionHelper(nums, used, target, k, 0, 0);
}
};
int recursion(int sum,int ind,int arr[],vector<vector<int>> &dp){
if(ind<0) {
if(sum==0) return 1;
return 0;
}
if(dp[ind][sum]!=-1) return dp[ind][sum];
int pick=0;
int notPick=recursion(sum,ind-1,arr,dp);
if(sum>=arr[ind]) pick=recursion(sum-arr[ind],ind-1,arr,dp);
return dp[ind][sum]=(pick+notPick)%mod;
}
int perfectSum(int arr[], int n, int sum)
{
vector<vector<int>> dp(n,vector<int>(sum+1,-1));
return recursion(sum,n-1,arr,dp);
}
int recursion(vector<vector<int>> &dp, vector<int> &arr, int ind, int target) {
if(ind<0) {
if (target == 0) return 1;
return 0;
}
if (dp[ind][target] != -1) return dp[ind][target];
int notPick = recursion(dp, arr, ind - 1, target);
int pick = 0;
if (target >= arr[ind]) pick = recursion(dp, arr, ind - 1, target - arr[ind]);
return dp[ind][target] = (pick + notPick)%mod;
}
int countPartitions(int n, int d, vector<int>& arr) {
int sum = accumulate(arr.begin(), arr.end(), 0);
if ((sum + d) % 2 != 0) return 0;
int target = (sum + d) / 2;
vector<vector<int>> dp(n, vector<int>(target + 1, -1));
return recursion(dp, arr, n - 1, target);
}
int recursion(int target,vector<int> &wt,vector<int> &val,int ind,vector<vector<int>> &dp){
if(ind==0){
if(wt[0]<=target) return val[0];
return 0;
}
if(dp[ind][target]!=-1) return dp[ind][target];
int pick=INT_MIN;
int notPick=0+recursion(target,wt,val,ind-1,dp);
if(wt[ind]<=target) pick=val[ind]+recursion(target-wt[ind],wt,val,ind-1,dp);
return dp[ind][target]=max(pick,notPick);
}
int knapSack(int target, vector<int>& wt, vector<int>& val) {
// Your code here
int n=wt.size();
vector<vector<int>> dp(n,vector<int>(target+1,-1));
return recursion(target,wt,val,n-1,dp);
}
class Solution {
public:
int recursion(vector<int> &coins,vector<vector<int>>&dp,int ind,int amt){
if(amt==0) return 0;
if(ind< 0 || amt<0) return 1e9;
if(dp[ind][amt]!=-1) return dp[ind][amt];
int notPick=recursion(coins,dp,ind-1,amt);
int pick=1e9;
if(amt>=coins[ind]) pick=1+recursion(coins,dp,ind,amt-coins[ind]);
return dp[ind][amt]=min(pick,notPick);
}
int coinChange(vector<int>& coins, int amount) {
int n=coins.size();
vector<vector<int>> dp(n,vector<int> (amount+1,-1));
int result=recursion(coins,dp,n-1,amount);
return result==1e9?-1:result;
}
};
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
int n=coins.size();
vector<vector<int>> dp(n,vector<int> (amount+1,1e9));
for(int i=0;i<n;i++) dp[i][0]=0;
for(int i=0;i<n;i++){
for(int amt=1;amt<=amount;amt++){
int notPick = (i > 0) ? dp[i - 1][amt] : 1e9;
int pick=1e9;
if(amt>=coins[i]) pick=1+dp[i][amt-coins[i]];
dp[i][amt]=min(pick,notPick);
}
}
int result= dp[n-1][amount];
return result==1e9?-1:result;
}
};
class Solution {
public:
int recursion(vector<vector<int>> &dp,vector<int> &nums,int ind,int target){
if(ind==0) {
if(target==0 && nums[0]==0) return 2;
if(target==nums[0] || target==0) return 1;
return 0;
}
if(dp[ind][target]!=-1) return dp[ind][target];
int pick=0;
int notPick=recursion(dp,nums,ind-1,target);
if(target>=nums[ind]) pick=recursion(dp,nums,ind-1,target-nums[ind]);
return dp[ind][target]=(pick+notPick);
}
int findTargetSumWays(vector<int>& nums, int target) {
int sum=accumulate(begin(nums),end(nums),0);
if (sum < abs(target) || (sum + target) % 2 != 0) return 0;
int n=nums.size();
target=(sum+target)/2;
vector<vector<int>> dp(n,vector<int>(target+1,-1));
return recursion(dp,nums,n-1,target);
}
};
Given two strings text1
and text2
, return *the length of their longest common subsequence . *If there is no common subsequence , return 0
.
A subsequence of a string is a new string generated from the original string with some characters (can be none) deleted without changing the relative order of the remaining characters.
"ace"
is a subsequence of "abcde"
.A common subsequence of two strings is a subsequence that is common to both strings.
Example 1:
Input: text1 = "abcde", text2 = "ace" Output: 3 Explanation: The longest common subsequence is "ace" and its length is 3.
Example 2:
Input: text1 = "abc", text2 = "abc" Output: 3 Explanation: The longest common subsequence is "abc" and its length is 3.
Example 3:
Input: text1 = "abc", text2 = "def" Output: 0 Explanation: There is no such common subsequence, so the result is 0.
Constraints:
1 <= text1.length, text2.length <= 1000
text1
and text2
consist of only lowercase English characters.class Solution {
public:
int recursion(int i,int j,string text1,string text2){
if(i<0 || j<0) return 0;
if(text1[i]==text2[j]) return 1+recursion(i-1,j-1,text1,text2);
return max(recursion(i-1,j,text1,text2),recursion(i,j-1,text1,text2));
}
int longestCommonSubsequence(string text1, string text2) {
int n=text1.size();
int m=text2.size();
return recursion(n-1,m-1,text1,text2);
}
};
class Solution {
public:
int recursion(int i,int j,string text1,string text2,vector<vector<int>> &dp){
if(i<0 || j<0) return 0;
if(dp[i][j]!=-1) return dp[i][j];
if(text1[i]==text2[j]) return dp[i][j]=1+recursion(i-1,j-1,text1,text2,dp);
return dp[i][j]= max(recursion(i-1,j,text1,text2,dp),recursion(i,j-1,text1,text2,dp));
}
int longestCommonSubsequence(string text1, string text2) {
int n=text1.size();
int m=text2.size();
vector<vector<int>> dp(n,vector<int>(m,-1));
return recursion(n-1,m-1,text1,text2,dp);
}
};
class Solution {
public:
int recursion(int i,int j,string text1,string text2,vector<vector<int>> &dp){
if(i==0 || j==0) return 0;
if(dp[i][j]!=-1) return dp[i][j];
if(text1[i-1]==text2[j-1]) return dp[i][j]=1+recursion(i-1,j-1,text1,text2,dp);
return dp[i][j]= max(recursion(i-1,j,text1,text2,dp),recursion(i,j-1,text1,text2,dp));
}
int longestCommonSubsequence(string text1, string text2) {
int n=text1.size();
int m=text2.size();
vector<vector<int>> dp(n+1,vector<int>(m+1,-1));
return recursion(n,m,text1,text2,dp);
}
};
1. Why is the memoization array shifted by 1?
The memoization array is shifted by 1 because the base case of the recursion is when i or j becomes 0. In the recursion, we are using 0-based indexing, so we need to shift the indices by 1 to match the base case of the recursion.
class Solution {
public:
int longestCommonSubsequence(string text1, string text2) {
int n=text1.size();
int m=text2.size();
vector<vector<int>> dp(n+1,vector<int>(m+1,0));
for(int i=0;i<n;i++) dp[i][0]=0;
for(int j=0;j<m;j++) dp[0][j]=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(text1[i-1]==text2[j-1]) dp[i][j]=1+dp[i-1][j-1];
else dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}
return dp[n][m];
}
};
class Solution {
public:
int longestCommonSubsequence(string text1, string text2) {
int n=text1.size();
int m=text2.size();
vector<int> prev(m+1,0),curr(m+1,0);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(text1[i-1]==text2[j-1]) curr[j]=1+prev[j-1];
else curr[j]=max(prev[j],curr[j-1]);
}
prev=curr;
}
return curr[m];
}
};
string findLCS(int n, int m,string &s1, string &s2){
vector<vector<int>> dp(n+1,vector<int> (m+1,0));
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(s1[i-1]==s2[j-1]) dp[i][j]=1+dp[i-1][j-1];
else dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}
int len=dp[n][m];
int i=n,j=m;
string ans;
int ind=len-1;
while(i>0 && j>0){
if(s1[i-1]==s2[j-1]){
ans.push_back(s1[i-1]);
ind--;
i--;
j--;
}
else if(dp[i-1][j]>dp[i][j-1]){
i--;
}
else {
j--;
}
}
reverse(begin(ans),end(ans));
return ans;
}
string findLCS(int n, int m,string &s1, string &s2){
vector<vector<int>> dp(n+1,vector<int> (m+1,0));
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(s1[i-1]==s2[j-1]) dp[i][j]=1+dp[i-1][j-1];
else dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}
int len=dp[n][m];
int i=n,j=m;
string ans(len,'-');
int ind=len-1;
while(i>0 && j>0){
if(s1[i-1]==s2[j-1]){
ans[ind]=s1[i-1];
ind--;
i--;
j--;
}
else if(dp[i-1][j]>dp[i][j-1]){
i--;
}
else {
j--;
}
}
return ans;
}
You are given two strings s
and t
. Now your task is to print all longest common subsequences in lexicographical order.
Note: A subsequence is derived from another string by deleting some or none of the elements without changing the order of the remaining elements.
Input:
s = abaaa
t = baabaca
Output:
aaaa
abaa
baaa
Explanation:
Length of LCS is 4. In lexicographical order, the longest common subsequences are:
aaaa, abaa, baaa
Input:
s = aaa
t = a
Output:
a
You do not need to read or print anything. Your task is to complete the function all_longest_common_subsequences()
which takes strings s
and t
as first and second parameters respectively and returns a list of strings that contains all possible longest common subsequences in lexicographical order.
O(n <sup>
3 </sup>
)
O(k * n) where k
is a constant less than n
.
//{ Driver Code Starts
#include <bits/stdc++.h>
using namespace std;
// } Driver Code Ends
class Solution {
public:
void recursion(vector<string> &ans,string &ds,int i,int j,vector<vector<int>> &dp,string s,string t){
if(i==0 && j==0){
reverse(begin(ds),end(ds));
ans.push_back(ds);
reverse(begin(ds),end(ds));
return;
}
if(s[i-1]==t[j-1]){
ds.push_back(s[i-1]);
recursion(ans,ds,i-1,j-1,dp,s,t);
ds.pop_back();
}
else {
if (i > 0 && dp[i-1][j] == dp[i][j]) recursion(ans, ds, i-1, j, dp, s, t);
if (j > 0 && dp[i][j-1] == dp[i][j]) recursion(ans, ds, i, j-1, dp, s, t);
}
}
vector<string> all_longest_common_subsequences(string s, string t) {
int n=s.size(),m=t.size();
vector<vector<int>> dp(n+1,vector<int> (m+1,0));
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(s[i-1]==t[j-1]) dp[i][j]=1+dp[i-1][j-1];
else dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}
vector<string> ans;
string ds;
recursion(ans,ds,n,m,dp,s,t);
set<string> st(ans.begin(),ans.end());
vector<string> ans2(st.begin(),st.end());
return ans2;
}
};
//{ Driver Code Starts.
int main() {
int T;
cin >> T;
while (T--) {
string s, t;
cin >> s >> t;
Solution ob;
vector<string> ans = ob.all_longest_common_subsequences(s, t);
for (auto i : ans)
cout << i << " ";
cout << "\n";
}
return 0;
}
// } Driver Code Ends
//{ Driver Code Starts
#include <bits/stdc++.h>
using namespace std;
// } Driver Code Ends
class Solution {
public:
void recursion(vector<vector<set<string>>> &memo,string &ds,int i,int j,vector<vector<int>> &dp,string s,string t,set<string>&temp){
if(i==0 && j==0){
reverse(begin(ds),end(ds));
temp.insert(ds);
reverse(begin(ds),end(ds));
return;
}
if(!memo[i][j].empty()) {
// temp.insert(memo[i][j].begin(),memo[i][j].end());
// return;
for (const string &subseq : memo[i][j]) {
temp.insert(subseq);
}
return;
}
if(s[i-1]==t[j-1]){
ds.push_back(s[i-1]);
recursion(memo,ds,i-1,j-1,dp,s,t,temp);
ds.pop_back();
}
else {
if (i > 0 && dp[i-1][j] == dp[i][j]) recursion(memo, ds, i-1, j, dp, s, t,temp);
if (j > 0 && dp[i][j-1] == dp[i][j]) recursion(memo, ds, i, j-1, dp, s, t,temp);
}
temp.insert(memo[i][j].begin(),memo[i][j].end());
}
vector<string> all_longest_common_subsequences(string s, string t) {
int n=s.size(),m=t.size();
vector<vector<int>> dp(n+1,vector<int> (m+1,0));
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(s[i-1]==t[j-1]) dp[i][j]=1+dp[i-1][j-1];
else dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}
string ds;
vector<vector<set<string>>> memo(n+1,vector<set<string>>(m+1));
set<string>temp;
recursion(memo,ds,n,m,dp,s,t,temp);
return vector<string>(temp.begin(), temp.end());
}
};
//{ Driver Code Starts.
int main() {
int T;
cin >> T;
while (T--) {
string s, t;
cin >> s >> t;
Solution ob;
vector<string> ans = ob.all_longest_common_subsequences(s, t);
for (auto i : ans)
cout << i << " ";
cout << "\n";
}
return 0;
}
// } Driver Code Ends
//{ Driver Code Starts
#include <bits/stdc++.h>
using namespace std;
// } Driver Code Ends
class Solution {
public:
void recursion(unordered_map<string,bool> &mp,string &ds,int i,int j,vector<vector<int>> &dp,string s,string t,set<string>&temp){
if(i==0 && j==0){
reverse(begin(ds),end(ds));
temp.insert(ds);
reverse(begin(ds),end(ds));
return;
}
string key=to_string(i)+','+to_string(j)+ds;
if(mp.find(key)!=mp.end()) return;
mp[key]=true;
if(s[i-1]==t[j-1]){
ds.push_back(s[i-1]);
recursion(mp,ds,i-1,j-1,dp,s,t,temp);
ds.pop_back();
}
else {
if (i > 0 && dp[i-1][j] == dp[i][j]) recursion(mp, ds, i-1, j, dp, s, t,temp);
if (j > 0 && dp[i][j-1] == dp[i][j]) recursion(mp, ds, i, j-1, dp, s, t,temp);
}
}
vector<string> all_longest_common_subsequences(string s, string t) {
int n=s.size(),m=t.size();
vector<vector<int>> dp(n+1,vector<int> (m+1,0));
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(s[i-1]==t[j-1]) dp[i][j]=1+dp[i-1][j-1];
else dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}
string ds;
unordered_map<string,bool> mp;
set<string>temp;
recursion(mp,ds,n,m,dp,s,t,temp);
return vector<string>(temp.begin(), temp.end());
}
};
//{ Driver Code Starts.
int main() {
int T;
cin >> T;
while (T--) {
string s, t;
cin >> s >> t;
Solution ob;
vector<string> ans = ob.all_longest_common_subsequences(s, t);
for (auto i : ans)
cout << i << " ";
cout << "\n";
}
return 0;
}
// } Driver Code Ends
//{ Driver Code Starts
#include <bits/stdc++.h>
using namespace std;
// } Driver Code Ends
class Solution {
public:
int longestCommonSubstr(string s, string t) {
// your code here
int n=s.size();
int m=t.size();
int ans=0;
vector<vector<int>> dp(n+1,vector<int>(m+1,0));
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(s[i-1]==t[j-1]) {
dp[i][j]=1+dp[i-1][j-1];
ans=max(ans,dp[i][j]);
}
}
}
return ans;
}
};
//{ Driver Code Starts.
int main() {
int t;
cin >> t;
while (t--) {
string s1, s2;
cin >> s1 >> s2;
Solution ob;
cout << ob.longestCommonSubstr(s1, s2) << endl;
}
}
// } Driver Code Ends
class Solution {
public:
int longestPalindromeSubseq(string s) {
string t=s;
reverse(begin(t),end(t));
int n=s.size();
vector<vector<int>>dp(n+1,vector<int>(n+1,0));
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(s[i-1]==t[j-1]) dp[i][j]=1+dp[i-1][j-1];
else dp[i][j]=max({dp[i-1][j],dp[i][j-1]});
}
}
return dp[n][n];
}
};
Delete Operation for Two Strings
class Solution {
public:
int minDistance(string word1, string word2) {
int m=word1.size();
int n=word2.size();
vector<vector<int>>dp(m+1,vector<int>(n+1,0));
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
if(word1[i-1]==word2[j-1]){
dp[i][j]=1+dp[i-1][j-1];
}
else{
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}
}
return m+n-2*dp[m][n];
}
};
class Solution {
public:
string shortestCommonSupersequence(string s, string t) {
int n=s.size(),m=t.size();
vector<vector<int>> dp(n+1,vector<int>(m+1,0));
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(s[i-1]==t[j-1]) dp[i][j]=1+dp[i-1][j-1];
else dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}
int i=n,j=m;
string ans;
while(i>0 && j>0){
if(s[i-1]==t[j-1]){
ans+=s[i-1];
i--;
j--;
}
else {
if(dp[i-1][j]>dp[i][j-1]){
ans+=s[i-1];
i--;
}
else {
ans+=t[j-1];
j--;
}
}
}
while(i>0){
ans+=s[i-1];
i--;
}
while(j>0){
ans+=t[j-1];
j--;
}
reverse(begin(ans),end(ans));
return ans;
}
};
class Solution {
public:
int recursion(string s,string t,int i,int j){
if(j<0) return 1;
if(i<0) return 0;
if(s[i]==t[j]){
return recursion(s,t,i-1,j-1)+recursion(s,t,i-1,j);
}
return recursion(s,t,i-1,j);
}
int numDistinct(string s, string t) {
int n=s.size();
int m=t.size();
return recursion(s,t,n-1,m-1);
}
};
class Solution {
public:
int recursion(string s,string t,int i,int j,vector<vector<int>> &dp){
if(j<0) return 1;
if(i<0) return 0;
if(dp[i][j]!=-1) return dp[i][j];
if(s[i]==t[j]){
return dp[i][j]=recursion(s,t,i-1,j-1,dp)+recursion(s,t,i-1,j,dp);
}
return dp[i][j]=recursion(s,t,i-1,j,dp);
}
int numDistinct(string s, string t) {
int n=s.size();
int m=t.size();
vector<vector<int>> dp(n,vector<int>(m,-1));
return recursion(s,t,n-1,m-1,dp);
}
};
class Solution {
public:
int recursion(string s,string t,int i,int j,vector<vector<int>> &dp){
if(j==0) return 1;
if(i==0) return 0;
if(dp[i][j]!=-1) return dp[i][j];
if(s[i-1]==t[j-1]){
return dp[i][j]=recursion(s,t,i-1,j-1,dp)+recursion(s,t,i-1,j,dp);
}
return dp[i][j]=recursion(s,t,i-1,j,dp);
}
int numDistinct(string s, string t) {
int n=s.size();
int m=t.size();
vector<vector<int>> dp(n+1,vector<int>(m+1,-1));
return recursion(s,t,n,m,dp);
}
};
class Solution {
public:
int numDistinct(string s, string t) {
int n=s.size();
int m=t.size();
vector<vector<double>> dp(n+1,vector<double>(m+1,0));
for(int i=0;i<=n;i++) dp[i][0]=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(s[i-1]==t[j-1]) dp[i][j]=dp[i-1][j-1]+dp[i-1][j];
else dp[i][j]=dp[i-1][j];
}
}
return (int)dp[n][m];
}
};
class Solution {
public:
int numDistinct(string s, string t) {
int n=s.size();
int m=t.size();
vector<double> prev(m+1,0),curr(m+1,0);
prev[0]=curr[0]=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(s[i-1]==t[j-1]) curr[j]=prev[j-1]+prev[j];
else curr[j]=prev[j];
}
prev=curr;
}
return (int)prev[m];
}
};
class Solution {
public:
int recursion(int i,int j,string s,string t){
if(i<0) return j+1;
if(j<0) return i+1;
if(s[i]==t[j]) return 0+recursion(i-1,j-1,s,t);
int insertion=1+recursion(i,j-1,s,t);
int deletion=1+recursion(i-1,j,s,t);
int replacement=1+recursion(i-1,j-1,s,t);
return min({insertion,deletion,replacement});
}
int minDistance(string s, string t) {
int n=s.size();
int m=t.size();
return recursion(n-1,m-1,s,t);
}
};
class Solution {
public:
int recursion(int i,int j,string s,string t,vector<vector<int>> &dp){
if(i<0) return j+1;
if(j<0) return i+1;
if(dp[i][j]!=-1) return dp[i][j];
if(s[i]==t[j]) return dp[i][j]=0+recursion(i-1,j-1,s,t,dp);
int insertion=1+recursion(i,j-1,s,t,dp);
int deletion=1+recursion(i-1,j,s,t,dp);
int replacement=1+recursion(i-1,j-1,s,t,dp);
return dp[i][j]=min({insertion,deletion,replacement});
}
int minDistance(string s, string t) {
int n=s.size();
int m=t.size();
vector<vector<int>> dp(n,vector<int>(m,-1));
return recursion(n-1,m-1,s,t,dp);
}
};
class Solution {
public:
int recursion(int i,int j,string s,string t,vector<vector<int>> &dp){
if(i==0) return j;
if(j==0) return i;
if(dp[i][j]!=-1) return dp[i][j];
if(s[i-1]==t[j-1]) return dp[i][j]=0+recursion(i-1,j-1,s,t,dp);
int insertion=1+recursion(i,j-1,s,t,dp);
int deletion=1+recursion(i-1,j,s,t,dp);
int replacement=1+recursion(i-1,j-1,s,t,dp);
return dp[i][j]=min({insertion,deletion,replacement});
}
int minDistance(string s, string t) {
int n=s.size();
int m=t.size();
vector<vector<int>> dp(n+1,vector<int>(m+1,-1));
return recursion(n,m,s,t,dp);
}
};
class Solution {
public:
int minDistance(string s, string t) {
int n=s.size();
int m=t.size();
vector<vector<int>> dp(n+1,vector<int>(m+1,0));
for(int i=0;i<=n;i++) dp[i][0]=i;
for(int j=0;j<=m;j++) dp[0][j]=j;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(s[i-1]==t[j-1]) dp[i][j]=dp[i-1][j-1];
else dp[i][j]=min({dp[i-1][j],dp[i][j-1],dp[i-1][j-1]})+1;
}
}
return dp[n][m];
}
};
class Solution {
public:
int minDistance(string s, string t) {
int n=s.size();
int m=t.size();
vector<vector<int>> dp(n+1,vector<int>(m+1,0));
vector<int> prev(m+1,0),curr(m+1,0);
for(int j=0;j<=m;j++) prev[j]=j;
for(int i=1;i<=n;i++){
curr[0]=i;
for(int j=1;j<=m;j++){
if(s[i-1]==t[j-1]) curr[j]=prev[j-1];
else curr[j]=min({prev[j],curr[j-1],prev[j-1]})+1;
}
prev=curr;
}
return prev[m];
}
};
class Solution {
public:
bool recursion(int i,int j,string p,string s){
if(i<0 && j<0) return true;
if(i<0 && j>=0) return false;
if(j<0 && i>=0) {
for(int x=0;x<=i;x++){
if(p[x]!='*') return false;
}
return true;
}
if(p[i]==s[j] || p[i]=='?') return recursion(i-1,j-1,p,s);
if(p[i]=='*'){
return recursion(i-1,j,p,s) || recursion(i,j-1,p,s);
}
return false;
}
bool isMatch(string s, string p) {
int n=s.size();
int m=p.size();
return recursion(m-1,n-1,p,s);
}
};
class Solution {
public:
bool recursion(int i,int j,string p,string s,vector<vector<int>> &dp){
if(i<0 && j<0) return true;
if(i<0 && j>=0) return false;
if(j<0 && i>=0) {
for(int x=0;x<=i;x++){
if(p[x]!='*') return false;
}
return true;
}
if(dp[i][j]!=-1) return dp[i][j]==1;
if(p[i]==s[j] || p[i]=='?') return dp[i][j]=recursion(i-1,j-1,p,s,dp);
if(p[i]=='*'){
return dp[i][j]=(recursion(i-1,j,p,s,dp) || recursion(i,j-1,p,s,dp));
}
return dp[i][j]=false;
}
bool isMatch(string s, string p) {
int n=s.size();
int m=p.size();
vector<vector<int>> dp(m,vector<int> (n,-1));
return recursion(m-1,n-1,p,s,dp);
}
};
class Solution {
public:
bool recursion(int i,int j,string p,string s,vector<vector<int>> &dp){
if(i==0 && j==0) return true;
if(i==0 && j>0) return false;
if(j==0 && i>0) {
for(int x=0;x<i;x++){
if(p[x]!='*') return false;
}
return true;
}
if(dp[i][j]!=-1) return dp[i][j]==1;
if(p[i-1]==s[j-1] || p[i-1]=='?') return dp[i][j]=recursion(i-1,j-1,p,s,dp);
if(p[i-1]=='*'){
return dp[i][j]=(recursion(i-1,j,p,s,dp) || recursion(i,j-1,p,s,dp));
}
return dp[i][j]=false;
}
bool isMatch(string s, string p) {
int n=s.size();
int m=p.size();
vector<vector<int>> dp(m+1,vector<int> (n+1,-1));
return recursion(m,n,p,s,dp);
}
};
class Solution {
public:
bool isMatch(string s, string p) {
int n=s.size();
int m=p.size();
vector<vector<bool>> dp(m+1,vector<bool> (n+1,0));
dp[0][0]=true;
for(int j=1;j<=n;j++) dp[0][j]=false;
for(int i=1;i<=m;i++){
int flag=true;
for(int x=0;x<i;x++){
if(p[x]!='*') {
flag=false;
break;
}
}
dp[i][0]=flag;
}
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
if(p[i-1]==s[j-1] || p[i-1]=='?') dp[i][j]=dp[i-1][j-1];
if(p[i-1]=='*') dp[i][j]= (dp[i-1][j] || dp[i][j-1]);
}
}
return dp[m][n];
}
};
class Solution {
public:
bool isMatch(string s, string p) {
int m=p.size();
int n=s.size();
vector<bool> prev(n+1,0),curr(n+1,0);
prev[0]=1;
for(int j=1;j<=n;j++) prev[j]=false;
for(int i=1;i<=m;i++){
bool flag=true;
for(int x=1;x<=i;x++){
if(p[x-1]!='*') {
flag=false;
break;
}
}
curr[0]=flag;
for(int j=1;j<=n;j++){
if(p[i-1]==s[j-1] || p[i-1]=='?') curr[j]=prev[j-1];
else if(p[i-1]=='*') curr[j]= (prev[j] || curr[j-1]);
else curr[j]=false;
}
prev=curr;
}
return prev[n];
}
};
class Solution {
public:
int maxProfit(vector<int>& prices) {
int mini=INT_MAX;
int ans=0;
for(int i=0;i<prices.size();i++){
ans=max(ans,prices[i]-mini);
mini=min(mini,prices[i]);
}
return ans;
}
};
class Solution {
public:
int recursion(int i,int n,bool buy,vector<int> &prices){
if(i==n) return 0;
if(buy){
// buying here iska matlab pesa jayega
int take=-prices[i]+recursion(i+1,n,false,prices); //profit
int notTake=0+recursion(i+1,n,true,prices);
return max(take,notTake);
}
else {
// selling here iska matlab pesa aayega
int take=prices[i]+recursion(i+1,n,true,prices); //profit
int notTake=recursion(i+1,n,false,prices);
return max(take,notTake);
}
}
int maxProfit(vector<int>& prices) {
int n=prices.size();
return recursion(0,n,true,prices);
}
};
### Memoization
```cpp
class Solution {
public:
int recursion(int i,int n,bool buy,vector<int> &prices,vector<vector<int>> &dp){
if(i==n) return 0;
if(dp[i][buy]!=-1) return dp[i][buy];
if(buy){
// buying here iska matlab pesa jayega
int take=-prices[i]+recursion(i+1,n,false,prices,dp); //profit
int notTake=0+recursion(i+1,n,true,prices,dp);
return dp[i][buy]=max(take,notTake);
}
else {
// selling here iska matlab pesa aayega
int take=prices[i]+recursion(i+1,n,true,prices,dp); //profit
int notTake=recursion(i+1,n,false,prices,dp);
return dp[i][buy]=max(take,notTake);
}
}
int maxProfit(vector<int>& prices) {
int n=prices.size();
vector<vector<int>> dp(n,vector<int>(2,-1));
return recursion(0,n,true,prices,dp);
}
};
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n=prices.size();
vector<vector<int>> dp(n+1,vector<int>(2,0));
for(int i=n-1;i>=0;i--){
for(int j=0;j<2;j++){
if(j==1){
int take=-prices[i]+dp[i+1][false];
int notTake=dp[i+1][true];
dp[i][j]=max(take,notTake);
}
else {
int take=prices[i]+dp[i+1][true];
int notTake=dp[i+1][false];
dp[i][j]=max(take,notTake);
}
}
}
return dp[0][1];
}
};
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n=prices.size();
vector<int> prev(2,0),curr(2,0);
for(int i=n-1;i>=0;i--){
for(int j=0;j<2;j++){
if(j==1){
int take=-prices[i]+prev[false];
int notTake=prev[true];
curr[j]=max(take,notTake);
}
else {
int take=prices[i]+prev[true];
int notTake=prev[false];
curr[j]=max(take,notTake);
}
}
prev=curr;
}
return prev[1];
}
};
class Solution {
public:
int recursion(int i,bool buy,int cap,vector<int> &prices,vector<vector<vector<int>>> &dp){
if(cap==0) return 0;
if(i==prices.size()) return 0;
if(dp[i][buy][cap]!=-1) return dp[i][buy][cap];
if(buy){
int take=-prices[i]+recursion(i+1,false,cap,prices,dp);
int notTake=recursion(i+1,true,cap,prices,dp);
return dp[i][buy][cap]=max(take,notTake);
}
else {
int take=prices[i]+recursion(i+1,true,cap-1,prices,dp);
int notTake=recursion(i+1,false,cap,prices,dp);
return dp[i][buy][cap]=max(take,notTake);
}
}
int maxProfit(vector<int>& prices) {
int n=prices.size();
vector<vector<vector<int>>> dp(n,vector<vector<int>>(2,vector<int>(3,-1)));
return recursion(0,true,2,prices,dp);
}
};
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n = prices.size();
if (n == 0 || n == 1)
return 0;
vector<vector<vector<int>>> dp(
n + 1, vector<vector<int>>(2, vector<int>(3, 0)));
for (int i = n - 1; i >= 0; i--) {
for (int buy = 0; buy < 2; buy++) {
for (int cap = 1; cap <=2; cap++) {
if (buy) {
int take = -prices[i] + dp[i + 1][false][cap];
int notTake = dp[i + 1][true][cap];
dp[i][buy][cap] = max(take, notTake);
} else {
int take = prices[i] + dp[i + 1][true][cap - 1];
int notTake = dp[i + 1][false][cap];
dp[i][buy][cap] = max(take, notTake);
}
}
}
}
return dp[0][1][2];
}
};
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n = prices.size();
if (n == 0 || n == 1)
return 0;
vector<vector<int>> prev(2,vector<int>(3,0)),curr(2,vector<int>(3,0));
for (int i = n - 1; i >= 0; i--) {
for (int buy = 0; buy < 2; buy++) {
for (int cap = 1; cap <=2; cap++) {
if (buy) {
int take = -prices[i] + prev[false][cap];
int notTake = prev[true][cap];
curr[buy][cap] = max(take, notTake);
} else {
int take = prices[i] + prev[true][cap - 1];
int notTake = prev[false][cap];
curr[buy][cap] = max(take, notTake);
}
}
}
prev=curr;
}
return prev[1][2];
}
};
int f(int ind,int ts,int n,vector<int>&prices,vector<vector<int>>&dp)
{
//base cases
if(ind == n || ts ==4) return 0;
if(dp[ind][ts] !=-1) return dp[ind][ts];
if(ts%2==0)
{
return dp[ind][ts] = max(-prices[ind]+f(ind+1,ts+1,n,prices,dp),f(ind+1,ts,n,prices,dp));
}
else
{
return dp[ind][ts] = max(prices[ind]+f(ind+1,ts+1,n,prices,dp),f(ind+1,ts,n,prices,dp));
}
}
int maxProfit(vector<int>& prices, int n)
{
// Write your code here.
vector<vector<int>>dp(n,vector<int>(4,-1));
return f(0,0,n,prices,dp);
}
int maxProfit(vector<int>& prices, int n)
{
// Write your code here.
vector<vector<int>>dp(n+1,vector<int>(5,-1));
for(int i=0;i<=4;i++)
{
dp[n][i] = 0;
}
for(int i=0;i<=n;i++)
{
dp[i][4]=0;
}
for(int ind=n-1;ind>=0;ind--)
{
for(int ts = 3;ts>=0;ts--)
{
if(ts%2==0)
{
dp[ind][ts] = max(-prices[ind]+dp[ind+1][ts+1],dp[ind+1][ts]);
}
else
{
dp[ind][ts] = max(prices[ind]+dp[ind+1][ts+1],dp[ind+1][ts]);
}
}
}
return dp[0][0];
}
int maxProfit(vector<int>& prices, int n)
{
// Write your code here.
vector<int>ahead(5,-1),cur(5,-1);
for(int i=0;i<=4;i++)
{
ahead[i] = 0;
}
cur[4]=0;
for(int ind=n-1;ind>=0;ind--)
{
for(int ts = 3;ts>=0;ts--)
{
if(ts%2==0)
{
cur[ts] = max(-prices[ind]+ahead[ts+1],ahead[ts]);
}
else
{
cur[ts] = max(prices[ind]+ahead[ts+1],ahead[ts]);
}
}
ahead = cur;
}
return ahead[0];
}
class Solution {
public:
int maxProfit(int k, vector<int>& prices) {
int n=prices.size();
vector<vector<vector<int>>> dp(n+1,vector<vector<int>>(2,vector<int>(k+1,0)));
for(int i=n-1;i>=0;i--){
for(int buy=0;buy<=1;buy++){
for(int cap=1;cap<=k;cap++){
if(buy){
dp[i][buy][cap]=max(-prices[i]+dp[i+1][false][cap],dp[i+1][true][cap]);
}
else {
dp[i][buy][cap]=max(prices[i]+dp[i+1][true][cap-1],dp[i+1][false][cap]);
}
}
}
}
return dp[0][1][k];
}
};
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n=prices.size();
vector<vector<int>> dp(n+2,vector<int>(2,0));
for(int i=n-1;i>=0;i--){
dp[i][1]=max(-prices[i]+dp[i+1][false],dp[i+1][true]);
dp[i][0]=max(prices[i]+dp[i+2][true],dp[i+1][false]);
}
return dp[0][1];
}
};
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n=prices.size();
vector<int> next1(2,0),curr(2,0),next2(2,0);
for(int i=n-1;i>=0;i--){
curr[1]=max(-prices[i]+next1[false],next1[true]);
curr[0]=max(prices[i]+next2[true],next1[false]);
next2=next1;
next1=curr;
}
return next1[1];
}
};
class Solution {
public:
int maxProfit(vector<int>& prices, int fee) {
int n=prices.size();
vector<vector<int>> dp(n+1,vector<int>(2,0));
for(int i=n-1;i>=0;i--){
dp[i][1]=max(-prices[i]+dp[i+1][0],dp[i+1][1]);
dp[i][0]=max(prices[i]+dp[i+1][1]-fee,dp[i+1][0]);
}
return dp[0][1];
}
};
class Solution {
public:
int maxProfit(vector<int>& prices, int fee) {
int n=prices.size();
vector<int> next(2,0),curr(2,0);
for(int i=n-1;i>=0;i--){
curr[1]=max(-prices[i]+next[0],next[1]);
curr[0]=max(prices[i]+next[1]-fee,next[0]);
next=curr;
}
return next[1];
}
};
class Solution {
public:
int recursion(int idx,int prevIdx,vector<int> &nums){
if(idx==nums.size()) return 0;
int notTake=recursion(idx+1,prevIdx,nums);
int take=0;
if(prevIdx==-1 || nums[idx]>nums[prevIdx]) take=1+recursion(idx+1,idx,nums);
return max(take,notTake);
}
int lengthOfLIS(vector<int>& nums) {
int n=nums.size();
return recursion(0,-1,nums);
}
};
class Solution {
public:
int recursion(int idx,int prevIdx,vector<int> &nums,vector<vector<int>> &dp){
if(idx==nums.size()) return 0;
if(dp[idx][prevIdx+1]!=-1) return dp[idx][prevIdx+1];
int notTake=recursion(idx+1,prevIdx,nums,dp);
int take=0;
if(prevIdx==-1 || nums[idx]>nums[prevIdx]) take=1+recursion(idx+1,idx,nums,dp);
return dp[idx][prevIdx+1]=max(take,notTake);
}
int lengthOfLIS(vector<int>& nums) {
int n=nums.size();
vector<vector<int>> dp(n,vector<int>(n+1,-1));
return recursion(0,-1,nums,dp);
}
};
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int n = nums.size();
vector<vector<int>> dp(n+1, vector<int>(n + 1, 0));
for (int idx = n - 1; idx >= 0; idx--) {
for (int prevIdx = idx-1; prevIdx >= -1; prevIdx--) {
int notTake = dp[idx + 1][prevIdx+1];
int take = 0;
if (prevIdx == -1 || nums[idx] > nums[prevIdx])
take = 1 + dp[idx + 1][idx+1] ;
dp[idx][prevIdx + 1] =max(take, notTake);
}
}
return dp[0][0];
}
};
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int n = nums.size();
vector<vector<int>> dp(n+1, vector<int>(n + 1, 0));
vector<int> next(n+1,0),curr(n+1,0);
for (int idx = n - 1; idx >= 0; idx--) {
for (int prevIdx = idx-1; prevIdx >= -1; prevIdx--) {
int notTake = next[prevIdx+1];
int take = 0;
if (prevIdx == -1 || nums[idx] > nums[prevIdx])
take = 1 + next[idx+1] ;
curr[prevIdx + 1] =max(take, notTake);
}
next=curr;
}
return next[0];
}
};
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int n = nums.size();
vector<int> dp(n+1,1);
int maxi=1;
for(int i=0;i<n;i++){
for(int prev=0;prev<i;prev++){
if(nums[prev]<nums[i]){
dp[i]=max(dp[i],1+dp[prev]);
}
}
maxi=max(maxi,dp[i]);
}
return maxi;
}
};
//{ Driver Code Starts
#include <bits/stdc++.h>
using namespace std;
// } Driver Code Ends
class Solution {
public:
vector<int> longestIncreasingSubsequence(int n, vector<int>& arr) {
// Code here
vector<int> ans;
vector<int> dp(n,1);
vector<int> hash(n,0);
int lastIndex=0;
int maxi=1;
for(int i=0;i<n;i++){
hash[i]=i;
for(int prev=0;prev<i;prev++){
if(arr[i]>arr[prev] && 1+dp[prev]>dp[i]){
dp[i]=1+dp[prev];
hash[i]=prev;
}
}
if(dp[i]>maxi){
maxi=dp[i];
lastIndex=i;
}
}
vector<int> lis;
lis.push_back(arr[lastIndex]);
int index=1;
while(hash[lastIndex]!=lastIndex){
lastIndex=hash[lastIndex];
lis.push_back(arr[lastIndex]);
}
reverse(begin(lis),end(lis));
return lis;
}
};
//{ Driver Code Starts.
int main() {
int t;
cin >> t;
while (t--) {
int N;
cin >> N;
vector<int> arr(N);
for (int i = 0; i < N; i++) {
cin >> arr[i];
}
Solution obj;
vector<int> res = obj.longestIncreasingSubsequence(N, arr);
for (auto x : res)
cout << x << " ";
cout << "\n";
}
return 0;
}
// } Driver Code Ends
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int n = nums.size();
vector<int> temp;
temp.push_back(nums[0]);
for (int i = 1; i < n; i++) {
if (nums[i] > temp.back())
temp.push_back(nums[i]);
else {
int ind =
lower_bound(begin(temp), end(temp), nums[i]) - begin(temp);
temp[ind] = nums[i];
}
}
return temp.size();
}
};
class Solution {
public:
vector<int> largestDivisibleSubset(vector<int>& nums) {
sort(nums.begin(),nums.end());
int n=nums.size();
vector<int> dp(n,1);
vector<int> hash(n);
iota(hash.begin(),hash.end(),0);
int maxi=0;
int lastIndex=0;
for(int i=0;i<n;i++){
for(int prev=0;prev<i;prev++){
if(nums[i]%nums[prev]==0 && dp[prev]+1>dp[i]){
dp[i]=dp[prev]+1;
hash[i]=prev;
}
}
if(dp[i]>maxi){
maxi=dp[i];
lastIndex=i;
}
}
vector<int> ans;
ans.push_back(nums[lastIndex]);
while(hash[lastIndex]!=lastIndex){
lastIndex=hash[lastIndex];
ans.push_back(nums[lastIndex]);
}
reverse(begin(ans),end(ans));
return ans;
}
};
class Solution {
public:
static bool cmp(string &s1,string &s2){
return s1.size()<s2.size();
}
bool checkPossible(string s1,string s2){
if (s1.size() != s2.size() + 1) return false;
int f=0,s=0;
while(f<s1.size()){
if(s<s2.size() && s1[f]==s2[s]){
s++;
}
f++;
}
return s == s2.size();
}
int longestStrChain(vector<string>& words) {
sort(begin(words),end(words),cmp);
int n=words.size();
vector<int> dp(n,1);
int maxi=1;
for(int i=0;i<n;i++){
for(int prev=0;prev<i;prev++){
if(checkPossible(words[i],words[prev]) && dp[i]<dp[prev]+1){
dp[i]=dp[prev]+1;
}
}
if(dp[i]>maxi){
maxi=max(dp[i],maxi);
}
}
return maxi;
}
};
int longestBitonicSubsequence(vector<int>& arr, int n)
{
// Write your code here.
vector<int> dp1(n,1),dp2(n,1);
for(int i=0;i<n;i++){
for(int j=0;j<i;j++){
if(arr[i]>arr[j])
dp1[i]=max(dp1[i],dp1[j]+1);
}
}
for(int i=n-1;i>=0;i--){
for(int j=n-1;j>i;j--){
if(arr[i]>arr[j])
dp2[i]=max(dp2[i],dp2[j]+1);
}
}
int ans=0;
for(int i=0;i<n;i++){
ans=max(ans,dp1[i]+dp2[i]-1);
}
return ans;
}
class Solution {
public:
int findNumberOfLIS(vector<int>& nums) {
int n=nums.size();
vector<int> dp(n,1);
vector<int> cnt(n,1);
int maxi=1;
for(int i=0;i<n;i++){
for(int j=0;j<i;j++){
if(nums[i]>nums[j] && dp[i]<dp[j]+1){
dp[i]=dp[j]+1;
cnt[i]=cnt[j];
}
else if(nums[i]>nums[j] && dp[i]==dp[j]+1){
cnt[i]+=cnt[j];
}
}
maxi=max(maxi,dp[i]);
}
int ans=0;
for(int i=0;i<n;i++){
if(dp[i]==maxi) ans+=cnt[i];
}
return ans;
}
};
int recursion(int i,int j,int arr[]){
if(i==j) return 0;
int mini=1e9;
for(int k=i;k<j;k++){
int steps=arr[i-1]*arr[k]*arr[j]+recursion(i,k,arr)+recursion(k+1,j,arr);
mini=min(mini,steps);
}
return mini;
}
int matrixMultiplication(int N, int arr[])
{
// code here
return recursion(1,N-1,arr);
}
int recursion(int i,int j,int arr[],vector<vector<int>> &dp){
if(i==j) return 0;
int mini=1e9;
if(dp[i][j]!=-1) return dp[i][j];
for(int k=i;k<j;k++){
int steps=arr[i-1]*arr[k]*arr[j]+recursion(i,k,arr,dp)+recursion(k+1,j,arr,dp);
mini=min(mini,steps);
}
return dp[i][j]=mini;
}
int matrixMultiplication(int N, int arr[])
{
// code here
vector<vector<int>> dp(N,vector<int>(N,-1));
return recursion(1,N-1,arr,dp);
}
int matrixMultiplication(int N, int arr[])
{
vector<vector<int>> dp(N,vector<int>(N,0));
for(int i=N-1;i>=1;i--){
for(int j=i+1;j<N;j++){
int mini=1e9;
for(int k=i;k<j;k++){
int steps=arr[i-1]*arr[k]*arr[j]+dp[i][k]+dp[k+1][j];
mini=min(mini,steps);
}
dp[i][j]=mini;
}
}
return dp[1][N-1];
}