0%

Stock Prices Series Problems

Buy and sell once

Leetcode 121. Best Time to Buy and Sell Stock

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Say you have an array for which the ith element is the price of a given stock on day i.

If you were only permitted to complete at most one transaction (i.e., buy one and sell one share of the stock), design an algorithm to find the maximum profit.

Note that you cannot sell a stock before you buy one.

Example 1:

Input: [7,1,5,3,6,4]
Output: 5
Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.
Not 7-1 = 6, as selling price needs to be larger than buying price.
Example 2:

Input: [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.

Solution

The max profit of current state only relevent to the previous minimium price. So we can use one variable to record the previous minimium price and update the current max profit.

The state transfer function is:

\[MaxProfit_{i} = Prices[i] - MinimumPrice\] \[MinimumPrice = min(MinimumPrice, Prices[i])\]

1
2
3
4
5
6
7
8
9
10
11
class Solution:
def maxProfit(self, prices: List[int]) -> int:
if not prices:
return 0
mini = prices[0]
res = 0
for p in prices[1:]:
res = max(res, p - mini)
mini = min(mini, p)

return res

Buy and sell multiple times

Leetocde 122 Best Time to Buy and Sell Stock II

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Say you have an array for which the ith element is the price of a given stock on day i.

Design an algorithm to find the maximum profit. You may complete as many transactions as you like (i.e., buy one and sell one share of the stock multiple times).

Note: You may not engage in multiple transactions at the same time (i.e., you must sell the stock before you buy again).


Example 1:

Input: [7,1,5,3,6,4]
Output: 7
Explanation: Buy on day 2 (price = 1) and sell on day 3 (price = 5), profit = 5-1 = 4.
Then buy on day 4 (price = 3) and sell on day 5 (price = 6), profit = 6-3 = 3.

Example 2:

Input: [1,2,3,4,5]
Output: 4
Explanation: Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 = 4.
Note that you cannot buy on day 1, buy on day 2 and sell them later, as you are
engaging multiple transactions at the same time. You must sell before buying again.

Example 3:

Input: [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.

Solution

  1. Mathemetical View

If we analyze the graph, we notice that the points of interest are the consecutive valleys and peaks. For example, in the above case, if we skip \(peak_i\) and \(vally_j\), trying to obtain more profit by considering points with more difference in heights, the net profit obtained will always be lesser than the one obtained by including them, Since:

\[C <= A + B\]

Therefore, we can find all the preak and valley pairs and calculate the total Profit:

\[TotalProfit = \sum_{i}( height(peak_i) - height(valley_i)) \]

1
2
3
4
5
6
7
8
class Solution:
def maxProfit(self, prices: List[int]) -> int:
res = 0
for i in range(1, len(prices)):
if prices[i] > prices[i-1]:
res += (prices[i] - prices[i-1])

return res
  1. Dynamic Programming

At the end of the \(i_{th}\) day, we maintain cash, the maximum profit we could have if we did not have a share of stock, and hold, the maximum profit we could have if we owned a share of stock.

The intution is the state of today is only relevent to the yesterday. The State of yesterday can be expressed as :

\[State_{yesterday} = [Profit, cash] \quad or \quad [Profit, hold]\]

Therefore , we can use two variables cash, hold to represent the above two states. The state transfer functions are:

  1. keep the same as day i-1, or sell from hold status at day i-1 \[cash = max(cash, hold + prices[i])\]
  2. keep the same as day i-1, or buy from cash status at day i-1 \[hold = max(hold, cash-prices[i])\]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution:
def maxProfit(self, prices: List[int]) -> int:

if not prices:
return 0

# the maximum profit we could have if we did not have a share of stock
cash = 0
# the maximum profit we could have if we owned a share of stock.
hold = -prices[0]

for i in range(1, len(prices)):
cash = max(cash, hold+prices[i])
hold = max(hold, cash-prices[i])

print(cash, hold)

return cash

Leetcode 714. Best Time to Buy and Sell Stock with Transaction Fee

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Your are given an array of integers prices, for which the i-th element is the price of a given stock on day i; and a non-negative integer fee representing a transaction fee.

You may complete as many transactions as you like, but you need to pay the transaction fee for each transaction. You may not buy more than 1 share of a stock at a time (ie. you must sell the stock share before you buy again.)

Return the maximum profit you can make.

Example 1:

Input: prices = [1, 3, 2, 8, 4, 9], fee = 2
Output: 8
Explanation: The maximum profit can be achieved by:
Buying at prices[0] = 1
Selling at prices[3] = 8
Buying at prices[4] = 4
Selling at prices[5] = 9
The total profit is ((8 - 1) - 2) + ((9 - 4) - 2) = 8.
Note:

0 < prices.length <= 50000.
0 < prices[i] < 50000.
0 <= fee < 50000.

Solution

  1. Dynamic Programming

See explanation above.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution:
def maxProfit(self, prices: List[int], fee: int) -> int:

# the maximum profit we could have if we did not have a share of stock
cash = 0
# the maximum profit we could have if we owned a share of stock.
hold = -prices[0]

for i in range(1, len(prices)):
cash = max(cash,hold+prices[i]-fee)
hold = max(hold, cash-prices[i])

return cash