递归股票最大化

时间:2017-08-23 09:24:12

标签: algorithm recursion memoization

问题是考虑到某一天的股票价格,最大化股票的利润。 我只能购买1支股票,卖出任何数字或什么都不做。

Test cases:
Input: 1 2 100
Output: 197
Explanation: Bought on day 1 and day 2 sold on day 3 total profit = (100 - 1) + (100 - 2) = 197

Input: 1 3 1 2
Output: 3
Explanation: buy one share on day 1, sell one on day 2, buy one share on day 3, and sell one share on day 4.

我在下面有一个递归解决方案,我知道还有其他解决方案,但我试图从递归的解决方案构建:

int maxProfit(vector<int> stock)
{
    int profit = helper(stock, stock[0], 1, 1);
    return profit < 0 ? 0 : profit;
}

int helper(vector<int>& stock, int cost, int index, int stockcount)
{
    if (index == stock.size() - 1)
    {
        return (stock[index] * stockcount) - cost;
    }
    int buy = helper(stock, cost + stock[index], index + 1, stockcount + 1);
    int sell = helper(stock, cost - stock[index], index + 1, stockcount - 1);
    return max(buy, sell);
}

算法是否是正确的重新计算方法,有没有办法记住上述内容?可能会删除累加器cost

3 个答案:

答案 0 :(得分:1)

您提供的递归解决方案似乎考虑了购买一只股票的选择,但忽略了无所作为的选择以及出售任意数量的自有股票的多种选择。

但最重要的是,它忽略了现实生活中最重要的优势:了解未来:)

如果您要从头到尾遍历数组,跟踪到目前为止的最高价格,请考虑一下如果:

(1)您遇到的价格是否低于您记录中的价格? (请记住,您的记录是未来价格)

和(2)您遇到的价格是否与您记录中的价格相同或更高? (再次请记住,您的记录中的价格是当前查看价格之后的最高价格)

(关于memoization - 一般来说,可以通过散列或为其参数集创建查找表来记忆函数的返回值,通过考虑哪些参数可以是常数或可以保持不变来进行优化,从而忽略如果您希望在计算过程中多次重复调用同一组参数,则记忆很有用。)

下面是一个JavaScript版本,其中包含您所描述的规则的记忆,然后是我在上面提到的O(n)反向遍历。

Memoized recursion:

&#13;
&#13;
function maxProfit(stock){
  return helper(stock, 0, 0, 0);
}

var hash = {};

function helper(stock, cost, index, stockcount){
  let key = [cost, index, stockcount].join('-');
  
  if (hash[key] !== undefined)
    return hash[key];

  if (index == stock.length)
    return -cost;

  var buy_or_not = helper(stock, cost + stock[index], index + 1, stockcount + 1);

  for (let i=0; i<=stockcount; i++)
    buy_or_not = Math.max(
      buy_or_not,
      helper(stock, cost - i*stock[index], index + 1, stockcount - i)
    );
      
  return hash[key] = buy_or_not;
}

console.log(maxProfit([1,1,50,1,1,50,1,1,40]));
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;
&#13;
&#13;

O(n)反向遍历:

&#13;
&#13;
function f(arr){
  if (!arr.length)
    return 0;
    
  var i = arr.length - 1,
      highest_sale_price = arr[i],
      stock_count = 0,
      current_cost = 0,
      total_profit = 0;
      
  for (i--; i>=0; i--){
    // Wouldn't want to buy this
    if (arr[i] >= highest_sale_price){
      
    // Go back to the future and
    // sell anything bought after
    // this day at the next highest
    // price
    total_profit += stock_count * highest_sale_price - current_cost;
    
    highest_sale_price = arr[i];
    current_cost = 0;
    stock_count = 0;

    // Otherwise, we know a 
    // higher future price
    // so buy this stock!
    } else {
      stock_count++;
      current_cost += arr[i];
    }
  }

  // Day 0, go back to the future and sell
  // anything we have left at a higher price
  if (highest_sale_price)
    total_profit += stock_count * highest_sale_price - current_cost;

  return total_profit;
}

console.log(f([1,1,50,1,1,50,1,1,40]));
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;
&#13;
&#13;

答案 1 :(得分:1)

术语 stock 是公司的特定所有权类别,例如英特尔的INTC或微软普通股的MSFT。您购买和销售的各个分区称为 shares

正如גלעדברקן已经指出的那样,你知道未来。没有猜测,没有美元平均,没有部分解决方案。您有完整的信息。

引理:如果出售1股股票是有意义的,那么卖出你所有的股票是有意义的。这将大大简化您的算法:您不必从1- N 中探索替代方案。

Lemma :如果今天的价格低于未来的最高价格,最好的策略是购买允许的最大价格。

<强>算法

// Base case:
If the array is empty, return

// Process
Find the maximum price in the array (call that day_s)
Buy max shares (one) on each day 1 : day_s
Sell all shares on day_s
(balance accounting is left as an exercise for the student)

// Recur
helper(stock[day_s: ], balance, 0)

答案 2 :(得分:0)

这是递归解决方案。在此解决方案中,我正在检查每个值i,以查看是否找到了j这样的值a[j] > a[i]。然后,我将利润计算为a[j] - a[i],然后将利润添加到从索引j + 1e的重复发生中。

 int solve(int *a, int s, int e, int k){
    // passing array a, starting index s, ending index e, max stocks one 
    // can sell k

    // base case
    if(s>=e)return 0;
    if(k == 0)return 0;

    int ans = 0;

    for(int i = s; i<e; i++){        
      for(int j = i+1; j<=e; j++){
        int temp =0;
        if(a[j]>a[i]){
          temp += a[j] - a[i] + solve(a,j+1,e,k-1); 
        }
        ans = max(ans,temp);
      }             
    }
    return ans;
  }