Got this question in an interview today, and its optimized solution stopped me cold (which blows, because I really wanted to work for this company...)
Given a single array of real values, each of which represents the stock value of a company after an arbitrary period of time, find the best buy price and its corresponding best sell price (buy low, sell high).
To illustrate with an example, let's take the stock ticker of Company Z:
55.39 109.23 48.29 81.59 105.53 94.45 12.24
Important to note is the fact that the array is "sorted" temporally - i.e. as time passes, values are appended to the right end of the array. Thus, our buy value will be (has to be) to the left of our sell value.
(in the above example, the ideal solution is to buy at 48.29
and sell at 105.53
)
I came up with the naive solution easily enough with O(n2) complexity (implemented in java):
// returns a 2-element array: first element is the index in the argument array
// of the best buying price, and the second element is the index of the best
// selling price which, collectively, maximize the trading return
//
// if there is no favorable trading (e.g. prices monotonically fall), null is returned
public int[] maximizeReturn(ArrayList<Double> prices) {
int [] retval = new int[2];
int BUY = 0, SELL = 1;
retval[BUY] = retval[SELL] = -1; // indices of buy and sell prices, respectively
for (int i = 0; i < prices.size(); i++) {
for (int j = i + 1; j < prices.size(); j++) {
double difference = prices.get(j).doubleValue() -
prices.get(i).doubleValue();
if (difference > 0.0) {
if (retval[BUY] < 0 || difference > prices.get(retval[SELL]).doubleValue() -
prices.get(retval[BUY]).doubleValue()) {
retval[BUY] = i;
retval[SELL] = j;
}
}
}
}
return (retval[BUY] > 0 ? retval : null);
}
Here's where I screwed up: there's a linear time O(n) solution, and I completely bombed in trying to figure it out (yeah, I know, FAIL). Does anyone know how to implement the linear time solution? (any language you're comfortable with) Thanks!
Edit
I suppose, for anyone interested, I just received word today that I didn't get the job for which I interviewed where they asked me this question. :(
The cost of a stock on each day is given in an array, find the max profit that you can make by buying and selling in those days. For example, if the given array is {100, 180, 260, 310, 40, 535, 695}, the maximum profit can earn by buying on day 0, selling on day 3. Again, buy on day 4 and sell on day 6.
In C#:
static void Main(string[] args)
{
double[] values = new double[7]{55.39, 109.23, 48.29, 81.59, 105.53, 94.45, 12.24};
double max = double.MinValue, maxDiff = double.MinValue, diff = 0;
for (int i = 1; i < values.Length; i++)
{
if (values[i] > values[i - 1])
{
//trending upward, append to existing differential
diff += values[i] - values[i - 1];
}
else
{
//trending downward, reset the diff
diff = 0;
}
if (diff > maxDiff)
{
maxDiff = diff;
max = values[i];
}
}
Console.WriteLine("Buy at {0}; Sell at {1}", max - maxDiff, max);
}
EDIT: New algo based on @Joe's failing test case -- Nice Catch BTW! It's also the same answer as @Doug T's now...
static void Main(string[] args)
{
double[] values = new double[8] { 55.39, 109.23, 48.29, 81.59, 81.58, 105.53, 94.45, 12.24 };
double max = double.MinValue, maxDiff = double.MinValue, diff = 0;
double bottom = values[0];
for (int i = 1; i < values.Length; i++)
{
diff += values[i] - values[i - 1];
if (diff > maxDiff)
{
maxDiff = diff;
max = values[i];
}
if (values[i] < bottom)
{
bottom = values[i];
diff = 0;
}
}
Console.WriteLine("Buy at {0}; Sell at {1}", max - maxDiff, max);
}
Here's an attempt (C++). Basically everytime I track a new top, I try to see if thats the best profit thusfar. I know that the "bottom" must have been discovered earlier. At that point I remember the top, bottom, and the current max profit. If a new bottom is discovered later, its AFTER the current top, so we must reset top and see if a slightly lower "top" can yield better profit.
#include <iostream>
int main()
{
double REALLY_BIG_NO = 1e99;
double bottom = REALLY_BIG_NO; // arbirtrary large number
double currBestBuy = 0.0;
double top = 0.0;
double currBestSell = 0.0;
double profit = 0.0;
// array of prices
double prices[] = {10.50, 55.39, 109.23, 48.29, 81.59, 105.53, 94.45, 12.24, 152.0, 2, 170.0};
int numPrices = 10;// number of prices
for (int i = 0; i < numPrices; ++i)
{
if (prices[i] < bottom)
{
bottom = prices[i];
// reset the search on a new bottom
top = 0.0;
}
else if (prices[i] > top)
{
top = prices[i];
// calculate profit
double potentialProfit = (top - bottom);
if (potentialProfit > profit &&
bottom != REALLY_BIG_NO)
{
profit = potentialProfit;
currBestSell = top;
currBestBuy = bottom;
}
}
}
std::cout << "Best Buy: " << currBestBuy << "Best Sell: " << currBestSell << std::endl;
}
So far I've played around with a bunch of different input sets, and so far I haven't had any problems... (let me know if you test this and see anything wrong)
I highly recommend using Austin Salonen's updated answer to this question and adapting it to your language.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With