微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

面试问题:投资股票的最大利润

如何解决面试问题:投资股票的最大利润

假设我们有 M 个硬币,我们想将其投资于股票。有 N 只股票,他可以投资一些非负整数。股票的利润 i 由二次函数给出:

AiXi2 + BiXi

其中 Xi 是投资于股票 i 的整数金额。 (−1000 ≤ Ai ≤ −1) & (1 ≤ Bi ≤ 1000)

设计一个贪心算法来找出我们可以赚到的最大金额?

不允许将零头资金投资于股票。我们可以投资不到 M 个币。

解决方法

贪心算法确实在这种情况下提供了最佳解决方案。

关键是,如果对于给定的股票,已经投资了 x 个硬币,那么下一次花费的预期收益等于:

next_gain = f(x+1) - f(x) = 2ax + a + b

由于 a 为负,此收益始终随 x(已投资的硬币数量)而减少。学究,增益函数是凹的。

那么很容易证明最优解是通过一个一个地花费硬币,寻找最大next_gain的股票。这可以通过 max_heap 实现,从而导致复杂性 O(M logN)

如果 M 非常大,则应预见其他解决方案,例如基于拉格朗日函数。在这种情况下将涉及更多的数学。正如您提到的,您正在寻找一种贪婪的解决方案,我认为这个贪婪的解决方案足够快。

这是 C++ 中的代码。应该很容易转换为任何具有最大堆的代码。

输出:

Profit = 16

#include <iostream>
#include <vector>
#include <queue>

struct Stock {
    int index;
    int n_bought;
    int next_gain;
    Stock (int i,int n,int gain) : index(i),n_bought(n),next_gain (gain) {};
    friend operator< (const Stock& x,const Stock& y) {return x.next_gain < y.next_gain;};
};

long long int profit (std::vector<int>& A,std::vector<int>& B,int M) {
    int n = A.size();
    if (n != B.size()) exit (1);
    std::priority_queue<Stock> candidates;
    
    for (int i = 0; i < n; ++i) {
        int gain = A[i] + B[i];
        if (gain > 0) candidates.emplace(Stock(i,gain));
    }
    long long int sum = 0.0;
    int coins = 0;
    while ((coins < M) &&(!candidates.empty())) {
        auto zebest = candidates.top();
        candidates.pop();
        coins++;
        sum += zebest.next_gain;
        zebest.n_bought++;
        int i = zebest.index;
        int gain = 2*A[i]*zebest.n_bought + A[i] + B[i];
        if (gain > 0) {
            zebest.next_gain = gain;
            candidates.push (zebest);
        }
    }
    return sum;
}

int main() {
    std::vector<int> A = {-2,-1,-2};
    std::vector<int> B = {3,5,10};
    int M = 3;

    auto ans = profit (A,B,M);
    std::cout << "Profit = " << ans << std::endl;
    return 0;
}
,

给定函数 Y = AiXi2 + BiXi 是二次函数。
对于约束条件,(-1000 ≤ Ai ≤ -1) 和 (1 ≤ Bi ≤ 1000) 投资可以表示为抛物线,


注意三件事:

  1. 这些抛物线的最大值由 X'i = -Bi / 2Ai 给定
  2. 我们应该总是投资硬币 Xi 使得 0 ≤ Xi ≤ X'i 以产生利润。
  3. 对于给定数量的代币 k,最好将它们投资于具有较大最大值的投资。

贪心算法是,

  1. 迭代所有 N 个投资,对于每一个我发现它是对应的 Xi = floor(X'i).
  2. 贪婪地进行所有这样的 k 项投资(首先投资最大 Xi)使得 Sum(Xi) ≤ M 所有这是我拍的。

这是帮助您入门的伪代码,

FIND_MAX(A,N,M):
    allProfits = [[]]
    for i = 1 to N:
        profit = []
        X = floor((-B[i]) / (2 * A[i]))
        profit.coins = X
        profit.index = i
        allProfits[i] =  profit
    Sort(allProfits)
    maxProfit = 0
    for j = N downto 1:
        if(M <= 0):
            break
        coins = min(allProfits[j].coins,M)
        i = allProfits[j].index
        maxProfit += (A[i] * coins * coins) + (B[i] * coins)
        M -= coins
    return maxProfit

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。