Algorithm 递归库存最大化

Algorithm 递归库存最大化,algorithm,recursion,memoization,Algorithm,Recursion,Memoization,问题是,给定一天的股票价格,如何使股票利润最大化。 我只能买一只股票,卖出任意数量的股票,或者什么都不做 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,

问题是,给定一天的股票价格,如何使股票利润最大化。 我只能买一只股票,卖出任意数量的股票,或者什么都不做

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);
}
int最大利润(矢量股票)
{
int-profit=helper(股票,股票[0],1,1);
回报利润<0?0:利润;
}
整数助手(向量和股票、整数成本、整数指数、整数股票计数)
{
if(index==stock.size()-1)
{
退货(库存[指数]*库存盘点)-成本;
}
int buy=helper(股票,成本+股票[指数],指数+1,股票计数+1);
int sell=helper(股票,成本-股票[指数],指数+1,股票计数-1);
返回最大值(买入、卖出);
}

该算法是一种正确的递归方法吗?有没有一种方法可以让我记住上述内容?可能删除累加器
成本

您提供的递归解决方案似乎考虑了购买一只股票的选择,但忽略了不做任何事情的选择以及出售任意数量的自有股票的各种选择

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

如果要从头到尾遍历阵列,跟踪到目前为止的最高价格,请考虑如果:

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

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

(关于记忆-一般来说,可以通过散列或为其参数集创建查找表来记忆函数的返回值,通过考虑哪些参数可能是常量或可能被设置为常量并因此被忽略来进行优化。如果希望多次调用同一组参数,则记忆非常有用。)(在计算过程中,重复使用s。)

下面是一个JavaScript版本,其中记录了您描述的规则,然后是我在上面暗示的
O(n)
反向遍历

记忆递归:

函数最大利润(股票){
返回帮助器(库存,0,0,0);
}
var hash={};
函数助手(库存、成本、指数、库存计数){
let key=[cost,index,stockcount].join('-');
if(散列[键]!==未定义)
返回散列[键];
如果(指数==股票长度)
收益-成本;
var buy_或_not=助手(股票、成本+股票[指数]、指数+1、股票计数+1);

对于(设i=0;i术语):股票是公司的特定所有权类别,如英特尔的INTC或微软普通股的MSFT。您买卖的各个分区称为股票

正如上文所指出的,你知道未来。没有猜测,没有平均值,没有局部解。你拥有全部信息

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

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

算法

// 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)

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

 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;
  }
int-solve(int*a,int-s,int-e,int-k){
//传递数组a、起始索引s、结束索引e、最大库存量1
//能卖k吗
//基本情况
如果(s>=e)返回0;
如果(k==0)返回0;
int ans=0;

对于(int i=s;其变化或售出的股票数量计入
stockcount
。要使递归不做任何事情,我可以添加另一个分支来只做
int donothing=helper(股票,成本,指数+1,stockcount)
-我可以按照你的建议去做,但这超出了递归解决这个问题的目的。@SamerTufail啊,我看到了股票数量。但是出售不同数量股票的选择似乎没有详细说明。在这个问题上,你的意思是?
出售任何数量
如果不清楚,我可以编辑它。@SamerTufail否,在你的ans中wer:)您只发布了销售一只股票的分支机构的递归(stockcount-1),但您说过,在每次迭代中,可以选择在零和所有当前拥有的股票之间进行出售。同意,但它确实考虑了在基本情况下出售的所有股票,在基本情况下,它最终使用股票计数进行出售。我在上一版本中有不同之处,在该版本中,出售中传递的参数等于
(股票[index]*stockcount)-成本
。我称之为
利润
,但为了简化记忆,我去掉了那个变量,并按上面的方式对它进行了编码。在每一步//都会重复出现,我在数组中找到最大值,或者这是一个预计算吗?@SamerTufail,预计算类似于
O(n)
我的答案中建议的反向遍历。从这个意义上说,这个答案中的递归似乎只是一个循环,没有选择点(分支)。@SamerTufail:“重现”仅仅是一个标签。@•㪞דבקן这是正确的:与许多递归例程一样,没有选择点。这将很容易转换为循环。这并不难解决,只是长时间运行。您可以在开始时继续,进行彻底的搜索。这项技术有很多示例,包括堆栈溢出和elsewher例如,你可以看看硬币兑换问题,看看这种多重递归风格的一个典型例子。我在我的答案中添加了代码,