valor una qué maximizar los las incrementar finanzas empresa definicion creacion como accionistas acciones arrays optimization complexity-theory stocks

arrays - qué - Encuentre precios de compra/venta en una variedad de valores de acciones para maximizar la diferencia positiva



valor de la empresa finanzas (23)

1. No podemos simplemente tomar la cantidad mínima entre los valores como "Best Buy" y la cantidad máxima como "Best Sell" porque "Sell" tiene que suceder después de "Buy".

2. No debemos tratar el mínimo registrado como la "Mejor compra" porque los días subsiguientes pueden tener valores de acciones cuya diferencia con el mínimo registrado puede generar ganancias que podrían ser menores que las "ganancias registradas".

3.Best Buy y Best Sell se tratan como una sola variante, ya que es la diferencia positiva entre estos valores la que produce el máximo beneficio.

4. Dado que cualquier mínimo registrado en el pasado es un posible candidato para la compra, la condición de beneficio máximo siempre se debe comparar con el mínimo registrado y el precio de las acciones del día actual. Por lo tanto, siempre debemos realizar un seguimiento del mínimo registrado, pero solo la presencia. El mínimo registrado no constituye "Best Buy" debido a la razón número 2.

Ahora tiene el siguiente código que se ejecuta en O (n) veces tendrá sentido.

public class BestStockBuyAndSell { public static void main(String[] args) { double[] stockPrices = {55.39,109.23,48.29,81.59,105.53,94.45,12.24}; int [] bestBuySellIndex = maxProfit(stockPrices); System.out.println("Best Buy At "+stockPrices[bestBuySellIndex[0]]); System.out.println("Best Sell At "+stockPrices[bestBuySellIndex[1]]); System.out.println("Max Profit = "+(stockPrices[bestBuySellIndex[1]]-stockPrices[bestBuySellIndex[0]])); } public static int[] maxProfit(double[] stockPrices) { int bestBuy=0; int bestSell=0; int[] bestCombination ={bestBuy,bestSell}; double recordedMinimum = stockPrices[bestBuy]; int recordedMinimuIndex = bestBuy; double bestProfitSofar = stockPrices[bestSell] - stockPrices[bestBuy]; for(int i=1;i<stockPrices.length;i++) { if(stockPrices[i] - recordedMinimum > bestProfitSofar) { bestProfitSofar = stockPrices[i] - recordedMinimum; bestSell = i; bestBuy = recordedMinimuIndex; } if(stockPrices[i] < recordedMinimum) { recordedMinimuIndex = i; recordedMinimum = stockPrices[i]; } } bestCombination[0] = bestBuy; bestCombination[1] = bestSell; return bestCombination; }

}

Recibí esta pregunta en una entrevista de hoy, y su solución optimizada me detuvo en seco (lo que me falla, porque realmente quería trabajar para esta compañía ...)

Dada una serie única de valores reales, cada uno de los cuales representa el valor de las acciones de una empresa después de un período de tiempo arbitrario, encuentra el mejor precio de compra y su correspondiente mejor precio de venta (comprar a bajo precio, vender alto).

Para ilustrar con un ejemplo, tomemos el indicador de acciones de la Compañía Z:

55.39 109.23 48.29 81.59 105.53 94.45 12.24

Es importante tener en cuenta el hecho de que la matriz está "ordenada" temporalmente, es decir, a medida que pasa el tiempo, los valores se agregan al extremo derecho de la matriz. Por lo tanto, nuestro valor de compra estará (debe estar) a la izquierda de nuestro valor de venta.

(En el ejemplo anterior, la solución ideal es comprar a 48.29 y vender a 105.53 )

Se me ocurrió la solución ingenua con la complejidad O (n 2 ) (implementada en 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); }

Aquí es donde la cagué: hay una solución O (n) de tiempo lineal , y bombardeé por completo para intentar resolverlo (sí, lo sé, FALLO). ¿Alguien sabe cómo implementar la solución de tiempo lineal? (cualquier idioma con el que te sientas cómodo) ¡Gracias!

Editar

Supongo que, para cualquier persona interesada, recibí la noticia de que no obtuve el trabajo por el que entrevisté donde me hicieron esta pregunta. :(


Aquí está mi implementación O (n) para esto. Estoy usando una matriz de cambios para calcular el máximo beneficio y las fechas de compra y venta. Sus comentarios sobre esto son bienvenidos.

#include<stdafx.h> #include<stdio.h> int main() { //int arr[10] = {15, 3, 5,9,10,1,6,4,7,2}; int arr[7] = {55.39, 109.23, 48.29, 81.59, 105.53, 94.45, 12.24}; int change[7]; int n=7; for(int i=1;i<=n;i++) { change[i] = arr[i]- arr[i-1]; } int i=0,index = 0; int sum = 0; int maxsum = 0; int startpos = 0; int endpos = 0; while(index < n) { sum = sum + change[index]; if(maxsum < sum) { maxsum = sum; startpos = i; endpos = index; } else if (sum<0) // negative number ,set sum to zero { sum = 0; i=index+1; } index++; } printf("max profit is%d %d %d", maxsum , startpos, endpos+1 ); }


Aquí está mi intento de usar Javascript. El script calcula la respuesta en O (N):

//Main Stock Array var stock = [15, 20, 0, 3, 30, 45, 67, 92, 1, 4, 99]; //Setup initial variable state var ans = {}, tmp = {}; //These are just for namespacing / syntatic sugar ans.minVal = stock[0]; ans.minInd = 0; ans.maxDiff = stock[1] - stock[0]; ans.maxInd = 1; tmp.minInd = ans.minInd; tmp.minVal = ans.minVal; //Basically we iterate throught the array. If we find a new low, we start tracking it. Otherwise we compare the current index against the previously found low for(i = 1; i <= stock.length-1; i++) { if(tmp.minVal > stock[i]) { tmp.minVal = stock[i]; tmp.minInd = i; } else { ans.diff = stock[i] - stock[tmp.minInd]; if(ans.diff > ans.maxDiff) { //Looks like we found a new maxDifference. Lets log the indexes ans.maxDiff = ans.diff; ans.maxInd = i; ans.minInd = tmp.minInd; ans.minVal = tmp.minVal; } } } document.write(''You should buy your stocks on day '' + ans.minInd + '' and sell on day '' + ans.maxInd);


Aquí está mi solución en Ruby:

values = [55.39, 109.23, 48.29, 81.59, 105.53, 94.45, 12.24] max_diff = 0 diff = 0 min = values[0] max = 0 values.each_with_index do |value, index = 1| # get an array of the previous values before the current one lag_values = values[0..index] # get the minimum of those previous values min_lag_value = lag_values.min # difference between current value and minimum of previous ones diff = values[index].to_i - min_lag_value.to_i # if current difference is > previous max difference, then set new values for min, max_diff, and max if diff > max_diff max_diff = diff min = min_lag_value max = values[index] end end min # => 48.29 max # => 105.3 max_diff # => 57

Aclamaciones


Aquí está mi solución, igual que @Doug T. excepto que también estoy haciendo un seguimiento del día en un índice. Por favor envíe sus comentarios.

int prices[] = {4,4,5,6,2,5,1,1}; //int prices[] = {100, 180, 260, 310, 40, 535, 695}; int currentBestSellPrice=0; int currentBestBuyPrice=0; int lowindex=0; int highindex=0; int low=prices[0]; int high=prices[0]; int profit=0; int templowindex=0; for(int i=0; i< prices.length;i++) { // buy low if(prices[i] < low && i+1 < prices.length) { low = prices[i]; templowindex=i; high=0; } // sell high else if(prices[i] > high) { high = prices[i]; int potentialprofit = (high-low); if(potentialprofit > profit) { profit = potentialprofit; currentBestSellPrice = high; currentBestBuyPrice = low; highindex=i; lowindex=templowindex; } } } System.out.println("Best Buy Price : "+ currentBestBuyPrice + " on day "+ lowindex); System.out.println("Best Sell Price : "+ currentBestSellPrice+ " on day "+ highindex );


Aquí hay un intento (C ++). Básicamente, cada vez que hago un seguimiento de un nuevo tope, trato de ver si ese es el mejor beneficio hasta ahora. Sé que el "fondo" debe haber sido descubierto antes. En ese momento recuerdo la parte superior, la parte inferior y la ganancia máxima actual. Si se descubre un nuevo fondo más tarde, es DESPUÉS de la parte superior actual, por lo que debemos restablecer la parte superior y ver si una "parte superior" ligeramente más baja puede producir mejores ganancias.

#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; }

Hasta ahora he jugado con un montón de conjuntos de entrada diferentes, y hasta ahora no he tenido ningún problema ... (Avísame si pruebas esto y ves algo incorrecto)

Recomiendo encarecidamente utilizar la respuesta actualizada de Austin Salonen a esta pregunta y adaptarla a su idioma.


Aquí hay una solución javascript ...

function getMax(arr){ //we need more than at least 3 ints to be able to do this if(arr.length <= 1) return arr; // get the minimum price we can sell at to make a profit var min = arr[0]; //get the first potential maximum profit var max = arr[1] - arr[0]; //while looping through we must get a potential value, //we can then compare that using the math.max using the maximum //and the potential prices that we have seen. Once the loop runs the ouput here should be 6! for(var i = 1; i < arr.length; ++i){ var current = arr[i]; var potential = current - min; max = Math.max(max, potential); min = Math.min(min, current); } return max; } console.log(getMax([10, 7, 5, 8, 11, 9]));

El tiempo de ejecución en esto es O (n)


Cía#:

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); }

EDITAR : Nuevo algo basado en el caso de prueba fallido de @ Joe - Nice Catch BTW! También es la misma respuesta que la de @Doug T ahora ...

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); }


En mi esfuerzo por aprender Go, y también en mi cerebro en este, aquí está mi intento.

func GetMaxProfit2(prices []float64) (float64, float64) { var min, max, pmin, pmax int for i, v := range prices { if v - prices[min] > prices[max] - prices[min] { pmax = max max = i } // Reset the max when min is updated. if v < prices[min] { pmin = min min = i pmax = max max = i } } // If min is ahead of max, reset the values back if min >= max { min = pmin max = pmax } return prices[min], prices[max] }


Esta es una solución C que realmente funciona:

void bestBuySell () {precios dobles [] = {10.50, 10.0, 3.0, 194.0, 55.39, 2.0, 109.23, 48.29, 81.59, 105.53, 94.45, 191.0, 200.0, 12.24}; int arrSize = 14; bestBuy doble = precios [0], bestSell = precios [1], bestPotentialBuy = precios [0]; doble potencialProfit = precios [1] - precios [0];

for(int i = 1; i < (arrSize-1); i++) { if(prices[i] < bestBuy) bestPotentialBuy = prices[i]; if((prices[i+1] - bestPotentialBuy) > potentialProfit) { bestBuy = bestPotentialBuy; bestSell = prices[i+1]; potentialProfit = prices[i+1] - bestPotentialBuy; } } printf( "bestBuy %f bestSell %f/n", bestBuy, bestSell );

}


F # solución para aquellos que estén interesados ​​en lo funcional. No diría que sea muy diferente.

let start, _, profit = [55.39; 109.23; 48.29; 81.59; 81.58; 105.53; 94.45; 12.24 ] |> Seq.fold (fun (start,newStart,profit) i -> let start = defaultArg start i let newStart = defaultArg newStart i let newProfit = i - newStart if profit < newProfit then Some newStart, Some newStart,newProfit else if start > i then Some start, Some i, profit else Some start,Some newStart,profit) (None,None, 0.0) printf "Best buy: %f; Best sell: %f" start.Value (start.Value + profit)

Salida:

Best buy: 48.290000; Best sell: 105.530000


La forma en que lo pensé fue que, para cada índice i ¿cuál sería el índice ideal para vender estas acciones? Esto es, por supuesto, el índice del valor máximo después de i . Esto reduce nuestro problema para encontrar el elemento máximo después del índice i para cada i en [1 ... n] Si pudiéramos hacerlo en O(n) , entonces podríamos encontrar la mejor opción entre ellos e informarlos.

Una forma de hacer esto es comenzar a atravesar desde el final de la matriz, manteniendo dos variables, una para guardar el elemento más grande que hemos encontrado hasta ahora max_till_now y otra para guardar la ganancia máxima que podríamos obtener hasta ahora, la profit . Esto es solo para que podamos hacer esto en una sola pasada. También podríamos usar espacio adicional y, para cada elemento i , almacenar el índice del elemento más grande en el rango [i + 1 ... n] para él y luego encontrar el beneficio máximo.

Aquí está mi código de python:

def buyLowSellHigh(L): length = len(L) profit = 0 max_till_now = L[length - 1] for i in xrange(length - 2, -1, -1): if L[i] > max_till_now: max_till_now = L[i] else: if max_till_now - L[i] > profit: profit = max_till_now - L[i] return profit


La idea es simple. Mantener dos punteros, lo y hola.
Hacer un loop de foor

  1. Si el precio es más alto que hola, actualice hi = precio, continúe
  2. Si el precio es más bajo que hola. Entonces lo y hola es uno de los posibles candidatos. Calcule la ganancia, guárdela si es más grande que las ganancias anteriores y reinicie lo, hola al precio

def getBestProfit(prices): lo = hi = profit = 0 for price in prices: if lo == 0 and hi == 0: lo = hi = price if price > hi: hi = price if price < low: tmpProfit = hi - lo if tmpProfit > profit: profit = tmpProfit lo = hi = price return profit

Eso es


Me gustaría describir cómo abordé este problema para facilitar la comprensión de mi código:

(1) Por cada día, si tuviera que vender mis acciones ese día, ¿cuál sería la cantidad mínima que podría haber pagado para comprarlas? Esencialmente, estoy haciendo un seguimiento del precio mínimo antes de ese día

(2) Por cada día, si tuviera que vender ese día, ¿cuánto estoy ganando? (Precio de las acciones en ese día - precio mínimo)

Esto demuestra que tengo que hacer un seguimiento de dos cosas: (1) el precio mínimo de las acciones hasta ahora (2) la mejor ganancia hasta ahora.

El problema se convierte en elegir qué día vender. Venderé el día que me dé la mejor ganancia. Aquí está mi código de Java:

public static void findBestDeal(double [] stocks) { double minsofar = stocks[0]; double bestsofar = 0.0; for(int i=1; i< stocks.length; i++) { // What is the cheapest price to buy it if I''m going to sell it today if(stocks[i-1] < minsofar) { minsofar = stocks[i-1]; } // How much do I earn if I sell it on ith day? double current_deal = stocks[i] - minsofar; // Is selling today better? if(current_deal > bestsofar) { bestsofar = current_deal; } } System.out.println("Found the best deal: " + bestsofar + " (Bought at " + minsofar + " and sold at " + (minsofar+bestsofar) + ")"); }


Otra solución de Ruby:

# Here''s some examples. Please feel free to give your new test. values = [55.39, 109.23, 48.29, 81.59, 105.53, 94.45, 12.24] # values = [5, 6, 4, 7, 9, 8, 8] # values = [5, 10, 4, 6, 7] # values = [5, 10, 4, 6, 12] # values = [1, 2, 3, 4, 5] # Initialize parameters. min = values[0] best_buy_time = values[0] best_sell_time = values[0] max_profit = 0 # This solution is based on comparing previous k elements and k+1 one. # The runtime is O(n) and it only use O(1) auxiliary storage. values.each_with_index do |value, index = 1| # Check value in this turn. puts value # Check current value is bigger than min or not. # If not, we find the new min. if value <= min min = value # If current value is bigger than min and # (value - min) is bigger than previous max_profit, # set new best_buy_time, best_sell_time & max_profit. else if value - min >= max_profit best_buy_time = min best_sell_time = value max_profit = value - min end end end # Let''s see about the result. puts "/nbest_buy_time: ", best_buy_time, "/nbest_sell_time: ", best_sell_time, "/nmax_profit: ", max_profit


Realmente tengo que señalar como una pregunta de entrevista que espera que usted la resuelva ya que O (n) es totalmente absurdo. Las preguntas de la entrevista están destinadas a demostrar que puede resolver un problema, y ​​usted pudo resolverlo. El hecho de que lo resolvieras en O (N ^ 2) vs O (N) debería ser irrelevante. Si una empresa dejara de contratarlo por no resolver esto en O (N), probablemente no sea una empresa en la que hubiera querido trabajar.


Se me ocurrió el siguiente algoritmo para este problema, parece funcionar para todas las entradas. Además, si el valor de las acciones sigue bajando, el programa no emitirá para comprar estas acciones:

public class GetMaxProfit { double minValue = -1, maxValue = -1; double maxDiff = 0; public void getProfit(double [] inputArray){ int i=0, j=1; double newDiff = 0; while(j<inputArray.length){ newDiff = inputArray[j]-inputArray[i]; if(newDiff > 0){ if(newDiff > this.maxDiff){ this.minValue = inputArray[i]; this.maxValue = inputArray[j]; this.maxDiff = newDiff; } } else{ i = j; } j++; } } public static void main(String[] args) { // TODO Auto-generated method stub GetMaxProfit obj = new GetMaxProfit(); obj.getProfit(new double[]{55.39, 19.23, 14.29, 11.59, 10.53, 9.45, 1.24}); if(obj.minValue != -1 && obj.maxValue != -1){ System.out.println("Buy Value for the input: "+obj.minValue); System.out.println("Sell Value for the input: "+obj.maxValue); System.out.println("Best profit for the input: "+obj.maxDiff); } else System.out.println("Do Not Buy This STOCK!!); } }

¿Hay alguna trampa que puedas encontrar en esto? Es la complejidad del tiempo es O (N)


Solución en javascript

var stockArr = [13931, 9889, 987, 4, 89, 100]; function getBestTime(sortedArr) { var min = 0; var buyIndx = 0; var saleIndx = 0; var maxDiff = 0; for (var i = 0; i < stockArr.length; i++) { if (stockArr[i] < stockArr[min]) { min = i; } var diff = stockArr[i] - stockArr[min]; if (diff > maxDiff) { buy = min; sale = i; maxDiff = diff; } } return { buy:buy+1, sale:sale+1, diff:maxDiff } } console.log(getBestTime(stockArr));


Solución en scala:

Ejemplo: [7, 2, 5, 6, 1, 3, 6, 4]

Mantenga un indicador del último precio mínimo de las acciones (lastStockPrice) y compárelo con el precio actual de las acciones. Cuando llega a un punto en el que el precio actual de las acciones <el último precio mínimo de las acciones, actualiza el último precio de inventario.

Mientras recorre la matriz, realice un seguimiento de la diferencia máxima (ganancia) entre el Precio actual y el Precio de la última compra, ya que la ganancia puede cambiar cuando actualice el Precio de la última venta.

El siguiente código de Scala funciona en tiempo O (n) y ocupa una cantidad constante de espacio.

object Solution { def maxProfit(prices: Array[Int]): Int = { var lastStockPrice = Int.MaxValue var maxProfit = 0 for(currentPrice <- prices){ if(currentPrice < lastStockPrice){ lastStockPrice = currentPrice; }else if(currentPrice - lastStockPrice > maxProfit){ maxProfit = currentPrice - lastStockPrice; } } maxProfit } }


Tengo el 100% para el mismo, aquí tienes.

public int solution(int[] A) { if (A == null || A.length<=1){ return 0; } int minValue = Math.min(A[0], A[1]); int profit = A[1] - A[0]; for (int i = 2; i < A.length; i++) { minValue = Math.min(minValue, A[i]); profit = Math.max(A[i] - minValue,profit); } return profit > 0 ? profit : 0; }


que tal esto

min = 100000000 max = 0 for elem in inp: if elem < min: min = elem tempMax = elem-min if tempMax > max: max = tempMax print(max)


public void profit(float stock[], int arlen ){ float buy = stock[0]; float sell = stock[arlen-1]; int bi = 0; int si = arlen - 1; for( int i = 0; i < arlen && bi < si ; i++){ if( stock[i] < buy && i < si){ buy = stock[i]; bi = i; } if(stock[arlen - i - 1] > sell && (arlen - i -1) > bi){ sell = stock[arlen - i - 1]; si = arlen - i - 1; } } System.out.println(buy+" "+sell); }


void getBestTime (int stocks[], int sz, int &buy, int &sell){ int min = 0; int maxDiff = 0; buy = sell = 0; for (int i = 0; i < sz; i++) { if (stocks[i] < stocks[min]) { min = i; } int diff = stocks[i] - stocks[min]; if (diff > maxDiff) { buy = min; sell = i; maxDiff = diff; } }}

Por si acaso prefieres esta respuesta. Lo encontré en otra web, pero aún así. fuente: http://leetcode.com/2010/11/best-time-to-buy-and-sell-stock.html