题目链接

题目描述

给定预测的天数 和股票第 天的收盘价 ,每天最多可操作一次,每次可以买入或卖出一股,或不操作。初始时无持仓,且不能做空;第 天收盘时必须清空所有持仓。请设计买卖策略,使得最终获得收益最大,并输出该最大收益。

解题思路

我们使用“反悔贪心”策略:维护一个最小堆来存储已买入的股价。遍历每一天的股价

  1. 入堆。
  2. 若堆顶价格小于当前价格 ,说明可以用最低买入价“反悔”并在当前价卖出一股,获得收益
    • 弹出堆顶,累加收益
    • 再将 入堆,保持与之后交易的衔接。 最终堆中元素会对应未被卖出的买入记录,变量 profit 为最大收益。该算法时间复杂度为 ,空间复杂度为

代码

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int main() {
    int n;
    cin >> n;
    vector<ll> p(n);
    for (int i = 0; i < n; ++i) {
        cin >> p[i];
    }
    priority_queue<ll, vector<ll>, greater<ll>> minHeap;
    ll profit = 0;
    for (int i = 0; i < n; ++i) {
        minHeap.push(p[i]);
        if (minHeap.top() < p[i]) {
            ll buy = minHeap.top();
            minHeap.pop();
            profit += p[i] - buy;
            minHeap.push(p[i]);
        }
    }
    cout << profit << '\n';
    return 0;
}
import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        long[] p = new long[n];
        for (int i = 0; i < n; ++i) {
            p[i] = sc.nextLong();
        }
        PriorityQueue<Long> minHeap = new PriorityQueue<>();
        long profit = 0;
        for (int i = 0; i < n; ++i) {
            minHeap.add(p[i]);
            if (minHeap.peek() < p[i]) {
                long buy = minHeap.poll();
                profit += p[i] - buy;
                minHeap.add(p[i]);
            }
        }
        System.out.println(profit);
    }
}
def main():
    n = int(input())
    p = list(map(int, input().split()))
    import heapq
    min_heap = []
    profit = 0
    for price in p:
        heapq.heappush(min_heap, price)
        if min_heap[0] < price:
            buy = heapq.heappop(min_heap)
            profit += price - buy
            heapq.heappush(min_heap, price)
    print(profit)

if __name__ == '__main__':
    main()

算法及复杂度

  • 算法:线性扫描“下降-上升”区间并贪心匹配,时间复杂度为
  • 时间复杂度:
  • 空间复杂度: