我有一个经典的面试问题要问,但它有一个转折点:
您将获得
天的股票价格,n
。您还将获得一个整数a1, a2, ..., an
。每天,您可以做三件事之一:1 <= k <= n
- 什么也不做
- 以当天的价格出售一单位股票。 (即使您的投资组合中没有任何股票,只要您的负债不超过
股票,您也可以出售)k
- 以当天价格购买一单位股票。
但是,您在任何时候最多可以拥有
股股票,或者您最多可以持有k
股股票。 因此,举例来说,如果您拥有k
股票,您可以 不 购买更多股票而不出售一些股票。找出你能获得的最大利润。另一个例子是,如果您已经k
股票负债累累,那么您就无法在不购买一些股票的情况下出售更多股票。k
您希望在第
n
天之后拥有净零库存。请比或O(nk)
更高效地完成此操作。O(n^2)
例如。O(n log k)
我可以在
O(nk)
中使用动态编程对我拥有的股票的日数和净数量来完成此操作。但我怎样才能更有效地做到这一点呢?
任何帮助将不胜感激。
谢谢!
您可以在 O(n log k) 时间内完成此操作。思考解决方案的方法有多种,但我认为最简单的方法是将其视为您已经了解的动态编程方法的优化。
假设您想要迭代这些日子,跟踪所持有的每种可能数量的股票的最佳现金头寸。我们会说 ci 是您持有 i 股的最多现金。要以价格 p 计算新的一天,对于每个 i,您执行 c'i = max( ci-1-p, ci+1+p, ci ),找到最佳方法通过分别买入一支、卖出一支或持有来获得 i 股。
我们可以观察/证明这些现金头寸的一些有趣的特性:
由于属性(2),我们不需要维护从每个 i 到 c 的映射。我们只需要维持一组差异,以及持有尽可能少的股份的最佳现金状况。
由于属性(3)和(4),我们需要对差异集进行的更改数量受常数限制。每天,您只需将 2 个 p 副本添加到差异集中,然后,如果差异超过 2k,则删除最高和最低的差异。
如果您以平衡 BST 或类似结构维护差异集,则这些添加和删除需要 log(k) 时间,从而导致总体算法为 O(n log k)。