**Java DP**

```
class Solution {
public int maxProfit(int[] p, int fee) {
int n = p.length;
if (n < 2) return 0;
int[] hold = new int[n], sold = new int[n];
hold[0] = -p[0];
for (int i = 1; i < n; ++i) {
hold[i] = Math.max(hold[i - 1], sold[i - 1] - p[i]);
sold[i] = Math.max(sold[i - 1], hold[i - 1] + p[i] - fee);
}
return sold[n - 1];
}
}
```

**C++ DP**

```
class Solution {
public:
int maxProfit(vector<int>& p, int fee) {
int n = p.size();
if (n < 2) return 0;
vector<int> hold(n, 0), sold(n, 0);
hold[0] = -p[0];
for (int i = 1; i < n; i++) {
hold[i] = max(hold[i - 1], sold[i - 1] - p[i]);
sold[i] = max(sold[i - 1], hold[i - 1] - fee + p[i]);
}
return sold[n - 1];
}
};
```

**Java Greedy**

- buy in - when current price higher than previous lowest point by more than amount of transaction fee, and set current price as highest point;
- sale out - when current price lower than prevous highest point by more than amount of transaction fee, and reset lowest, highest
- update highest - only if highest is set;
- update lowest - every day

```
class Solution {
public int maxProfit(int[] p, int fee) {
int profit = 0;
Integer lo = null, hi = null, n = p.length;
for (int i = 0; i < n; i++) {
if (lo != null && hi == null && p[i] - lo > fee) hi = p[i]; // buy in
if (hi != null && p[i] > hi) hi = p[i]; // update highest
if (hi != null && (hi - p[i] > fee || i == n - 1)) { // sale out
profit += hi - lo - fee;
hi = null;
lo = null;
}
lo = lo != null ? Math.min(lo, p[i]) : p[i]; // update lowest
}
return profit;
}
}
```

**C++ Greedy**

```
class Solution {
public:
int maxProfit(vector<int>& p, int fee) {
int profit = 0;
int* lo = nullptr, *hi = nullptr, n = p.size();
for (int i = 0; i < n; i++) {
if (lo && !hi && p[i] - *lo > fee) hi = &p[i]; // buy in
if (hi && p[i] > *hi) hi = &p[i]; // update highest
if (hi && (*hi - p[i] > fee || i == n - 1)) { // sale out
profit += *hi - *lo - fee;
hi = nullptr;
lo = nullptr;
}
if (!lo || p[i] < *lo) lo = &p[i]; // update lowest
}
return profit;
}
```