Stock price processing problem

Question


You are given a stream of records about a particular stock. Each record contains a timestamp and

 the corresponding price of the stock at that timestamp.


Unfortunately due to the volatile nature of the stock market, the records do not come in order.

Even worse, some records may be incorrect.

 Another record with the same timestamp may appear later in the stream 

 correcting the price of the previous wrong record.


Design an algorithm that:


Updates the price of the stock at a particular timestamp,

correcting the price from any previous records at the timestamp.

Finds the latest price of the stock based on the current records.

The latest price is the price at the latest timestamp recorded.

Finds the maximum price the stock has been based on the current records.

Finds the minimum price the stock has been based on the current records.

Implement the StockPrice class:


StockPrice() Initializes the object with no price records.

void update(int timestamp, int price) Updates the price of the stock at the given timestamp.

int current() Returns the latest price of the stock.

int maximum() Returns the maximum price of the stock.

int minimum() Returns the minimum price of the stock.

 

Example 1:


Input

["StockPrice", "update", "update", "current", "maximum", "update", "maximum", "update", "minimum"]

[[], [1, 10], [2, 5], [], [], [1, 3], [], [4, 2], []]

Output

[null, null, null, 5, 10, null, 5, null, 2]


Explanation

StockPrice stockPrice = new StockPrice();

stockPrice.update(1, 10); // Timestamps are [1] with corresponding prices [10].

stockPrice.update(2, 5);  // Timestamps are [1,2] with corresponding prices [10,5].

stockPrice.current();     // return 5, the latest timestamp is 2 with the price being 5.

stockPrice.maximum();     // return 10, the maximum price is 10 at timestamp 1.

stockPrice.update(1, 3);  // The previous timestamp 1 had the wrong price, so it is updated to 3.

                          // Timestamps are [1,2] with corresponding prices [3,5].

stockPrice.maximum();     // return 5, the maximum price is 5 after the correction.

stockPrice.update(4, 2);  // Timestamps are [1,2,4] with corresponding prices [3,5,2].

stockPrice.minimum();     // return 2, the minimum price is 2 at timestamp 4.

 

Constraints:

1 <= timestamp, price <= 109

At most 105 calls will be made in total to update, current, maximum, and minimum.

current, maximum, and minimum will be called only after the update has been called at least once.



Solution


Initial approach (Failed on reserved ordered stocks by price)


Given that we are getting the stock price information in random order and this problem only needs to report three pieces of information: current price, minimum price, and max price. It seems quite a straightforward problem, which could be solved by remembering the MAX, MIN, and CURRENT(latest) prices.  However,  the following condition complicates the problem.

Even worse, some records may be incorrect. Another record with the same timestamp may appear later in the stream correcting the price of the previous wrong record.

When the next stock price overwrites the existing MAX price or MIN price for the same timestamp to a smaller or larger price, we need to find the next largest one or next smallest one to provide the correct MAX or MIN value.

This means we need to keep the previous prices in order and should be able to access both max and min values quickly. 

We also need to remember the price for each timestamp for later correction as well.

Given the requirements, I thought of creating the binary search tree with a counter to remember the occurrence of the prices. The reason for having counters was that there could be multiple identical prices for the same timestamp. When the same price as the existing price is added, we increase the count by 1 and when the old price is corrected to a new price, we will decrease the old price by 1 and increase the counter of the new price by 1. If the old price count becomes zero, we will remove it from the tree. If the new price does not exist in the tree, we will add the price to the tree with the count of 1.

With this solution, the time complexity of CURRENT, MAX, and MIN is $O(1)$, $O(logN)$, $(logN)$ respectively.

The only problem with this solution is that I did not have to rebalance logic to keep the height of the binary search tree to stay optimal. Due to that, my solution was too slow for large stock prices coming in descending order thereby making the height of my tree, N and making both MAX and MIN operations run in $O(N)$

Here is the solution in Python.

A better approach using SortedDict

To overcome the inefficiency, the second solution is stored in the SortedDict data object which provides two key features. This is part of the sortedconainers module.

Allow finding the value with a key like a dictionary, O(1) time
Keep the elements in order all the time and allow to get the value via the index in O(1) time

This can replace the binary search tree to keep the price (as Key) and count ( as Value).

I believe this data structure implements the perfect binary search tree under the hood.

Here is a much shorter but working solution using SortedDict.






 

Comments

Popular posts from this blog

Planting flowers with no adjacent flower plots

Find the maximum number of bomb that can be detonated