from typing import List
Problem Description
Difficulty: Easy
Given an array of prices
where prices[i]
indicates the cost of a specific asset on the i
th day. Optimize the returns by selecting one day to purchase the asset and a subsequent day to sell it. Determine the highest possible profit. If no profit can be made, return 0
.
Example 1:
Input: prices = [8, 2, 4, 7, 3, 5]
Output: 5
Explanation: Buy on day 2 (price = 2) and sell on day 4 (price = 7); the profit is 7 - 2 = 5.
Example 2:
Input: prices = [9, 7, 6, 3, 1]
Output: 0
Explanation: No profitable transactions are possible, so the maximum profit is 0.
Initial Solution
class Solution:
def maxProfit(self, prices: List[int]) -> int:
= 0 # buy-price pointer
l = 0 # sell-price pointer
r = 0
max_profit
while r < len(prices):
= prices[r] - prices[l]
profit = max(max_profit, profit)
max_profit if prices[l] > prices[r]:
+= 1
l else:
+= 1
r
return max_profit
= Solution()
solution # Test cases
assert solution.maxProfit([8, 2, 4, 7, 3, 5]) == 5
assert solution.maxProfit([9, 7, 6, 3, 1]) == 0
assert solution.maxProfit([1, 2]) == 1
print("Tests completed")
Tests completed
Initial Results:
I addressed this problem with a two-pointer algorithm that is basically a variable sliding window. The above code beat 94% of LeetCode submissions on runtime and 97% on memory. This was somewhat surprising for my first attempt, so I took a screenshot (image below). Most submissions used a for
loop, also in linear time, but presumably with some additional calculations within. I created another version with a for
loop, which is likely a cleaner way of doing this, but the speed was about the same.
Complexity
- Time complexity: \(O(n)\) as the pointers traverse the input list only once (
l
andr
only increase and do not reset). - Space complexity: \(O(1)\) as no additional space is used that would grow with input size.
NeetCode Solution
class Solution:
def maxProfit(self, prices: List[int]) -> int:
= 0
res = prices[0]
lowest for price in prices:
if price < lowest:
= price
lowest = max(res, price - lowest)
res return res
This solution also has \(O(n)\) time complexity. However, NeetCode’s is more elegant with fewer operations. On LeetCode, it ran in 74 ms and beat around 97% of submissions on time and space.
Interestingly, LeetCode’s youtube video has a different solution to that given on the website, without any explanation for the difference. It’s shown below and ran in 118 ms. It’s a little better than mine as the profit is only calculated when the price at l
is less than the price at r
, which avoids some unnecessary calculations. The l = r
part, instead of l += 1
, should allow it to skip ahead quicker too. I tried that out in my code above, and it didn’t seem to make much difference though.
class Solution:
def maxProfit(self, prices: List[int]) -> int:
= 0, 1
l, r = 0
maxP while r < len(prices):
if prices[l] < prices[r]:
= prices[r] - prices[l]
profit = max(maxP, profit)
maxP else:
= r
l += 1
r return maxP