The basic idea is to create two tables. hold and unhold.

hold[i][j] means the maximum profit with at most j transaction for 0 to i-th day. hold means you have a stock in your hand.

unhold[i][j] means the maximum profit with at most j transaction for 0 to i-th day. unhold means you don't have a stock in your hand.

The equation is

hold[i][j] = Math.max(unhold[i-1][j]-prices[i],hold[i-1][j]);

unhold[i][j] = Math.max(hold[i-1][j-1]+prices[i],unhold[i-1][j]);

when you sell your stock this is a transaction but when you buy a stock, it is not considered as a full transaction. so this is why the two equation look a little different.

And we have to initiate hold table when **k = 0**.

When the situation is you can not buy a new stock at the same day when you sell it. For example you can only buy a new stock after one day you sell it. The same idea. Another situation is when you have to pay a transaction fee for each transaction, just make a modification when you sell it, So just change the unhold equation a little.

```
public class Solution {
//hold[i][k] ith day k transaction have stock and maximum profit
//unhold[i][k] ith day k transaction do not have stock at hand and maximum profit
public int maxProfit(int k, int[] prices) {
if(k>prices.length/2) return maxP(prices);
int[][] hold = new int[prices.length][k+1];
int[][] unhold = new int[prices.length][k+1];
hold[0][0] = -prices[0];
for(int i=1;i<prices.length;i++) hold[i][0] = Math.max(hold[i-1][0],-prices[i]);
for(int j=1;j<=k;j++) hold[0][j] = -prices[0];
for(int i=1;i<prices.length;i++){
for(int j=1;j<=k;j++){
hold[i][j] = Math.max(unhold[i-1][j]-prices[i],hold[i-1][j]);
unhold[i][j] = Math.max(hold[i-1][j-1]+prices[i],unhold[i-1][j]);
}
}
return Math.max(hold[prices.length-1][k],unhold[prices.length-1][k]);
}
public int maxP(int[] prices){
int res =0;
for(int i=0;i<prices.length;i++){
if(i>0 && prices[i] > prices[i-1]){
res += prices[i]-prices[i-1];
}
}
return res;
}
}
```