Example: Stock Buy Sell - rFronteddu/general_wiki GitHub Wiki

You are given stock prices on several days and have to get the max profit by doing at most k transactions. Furthermore, transactions cannot happen in parallel.

Strategy:

  • i: number of transactions
  • j: day
  • t[i,j] = max(
    • t[i,j-1] value by not doing a transaction on day j
    • p[j] - p[m] + t[i-1,m] best you can get by completing a transaction on day m. Note that we have to find m = 0..j-1
--- 0 1 2 3 4 5 6 7
--- 2 5 7 1 4 3 1 3
0 0 0 0 0 0 0 0 0
1 0 3 5 5 5 5 5 5
2 0 3 5 5 8 8 8 8
3 0 3 5 5 8 8 8 10

While we test the relation, we notice that we don't really need to check all the values between 0 and j-1

Consider d[2,3]

  • m=0 => T[1,0] - price[0] + price[3]
  • m=1 => T[1,1] - price[1] + price[3]
  • m=2 => T[1,2] - price[2] + price[3]

Consider d[2,4]

  • m=0 => T[1,0] - price[0] + price[4]
  • m=1 => T[1,1] - price[1] + price[4]
  • m=2 => T[1,2] - price[2] + price[4]
  • m=3 => T[1,3] - price[3] + price[4]

For each j, we can keep track of the maxDiff and update it with the new value of m=j-1 if the new one is larger

  • d[i,j] = p[j] + max(maxDiff, t[i-1,j-1] - p[j-1])
// p: stock prices per day
// tr: number of transactions
// p: [0..n]
stock(p, tr)
    let d[0..tr, 0..p.len-1]
    for i = 1 to tr
        maxDiff = -inf
        for j = 0 to p.len-1
            // m can only get to j-1, so the latest m to test is j-1
            c = d[i-1, j-1] - p[j-1]
            if c > maxDiff
                maxDif = c
            d[i,j] = max(d[i, j-1], p[j] + maxDiff)

    i = tr
    j = x.len-1
    l = []
    while i > 0 && j > 0
        // find where current number comes from
        if d[i, j] == d[i,j-1]
            j--
        else 
            sellDay = j
            buyDay = j--
            prevProfit = d[i, j] - p[sellDay]
            while (prevProfit !=  d[i-1, j] - p[buyDay]) {
                buyDay--
            }
            l.insert(0, (buyDay, sellDay))
    print ("Max profit: " + d[tr, p.len-1])
    return l