I'm Prime

十方三世,尽在一念

View on GitHub

leetcode 笔记


题目描述

给定一个整数数组 prices ,它的第 i 个元素 prices[i] 是一支给定的股票在第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

示例 1

输入:k = 2, prices = [2,4,1]
输出:2
解释:在第 1  (股票价格 = 2) 的时候买入,在第 2  (股票价格 = 4) 的时候卖出,这笔交易所能获得利润 = 4-2 = 2 
示例 2

输入:k = 2, prices = [3,2,6,5,0,3]
输出:7
解释:在第 2  (股票价格 = 2) 的时候买入,在第 3  (股票价格 = 6) 的时候卖出, 这笔交易所能获得利润 = 6-2 = 4 
     随后,在第 5  (股票价格 = 0) 的时候买入,在第 6  (股票价格 = 3) 的时候卖出, 这笔交易所能获得利润 = 3-0 = 3 
 

提示:
0 <= k <= 10^9
0 <= prices.length <= 1000
0 <= prices[i] <= 1000

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iv
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

code

class Solution
{
public:
    int maxProfit(int k, vector<int> &prices)
    {
        int size = prices.size();
        if (size < 2 || k == 0)
            return 0;

        k = min(k, size / 2);
        vector<int> b(k + 1, -1000), s(k + 1, 0);
        
        for (int v : prices)
            for (int j = 1; j <= k; ++j)
            {
                b[j] = max(b[j], s[j - 1] - v);
                s[j] = max(s[j], b[j] + v);
            }
        return s.back();
    }
};

拆解:

// 最多可做的交易数
k = min(k, size / 2);

for (int v : prices){

    // i - 1天过后,每笔交易完成后的最优解
    vector<int> pre = s;

    for (int j = 1; j <= k; ++j)
    {
        // b[j] 存第 j 笔交易买入后的结果
        // 所以如果买第i天的股票。则可获得的金额为: 当前第j - 1笔交易完成后的结果pre[j - 1] - 股票价格
        // 与当前的购买方案比较留下最优解。
        // 由于此时s[j - 1]并没有任何修改,pre[j - 1] == s[j - 1]
        b[j] = max(b[j], pre[j - 1] - v);

        // s[j] 存第 j 笔交易完成时的结果
        // 如果按第 i 天价格卖出,则可获得的金额为: 当前第j笔交易买入后的结果b[j] + 股票价格
        // 与当前卖出方案留最优解。
        // 同上,由于此时s[j]并没有任何修改,pre[j] == s[j], 所以pre数组可以免掉
        s[j] = max(pre[j], b[j] + v);
    }
}

一刀流,没意义。 涉及下标访问的,函数式都差点意思。

fun maxProfit(k: Int, prices: IntArray): Int = prices.fold(Array(min(k, prices.size / 2) + 1) { -1000 to 0 }) { arr, v -> arr.apply { (1..arr.lastIndex).forEach { i -> arr[i] = max(arr[i].first, arr[i - 1].second - v) to max(arr[i].second, arr[i].first + v) } } }.last().second
import kotlin.math.min
import kotlin.math.max

class Solution {
    fun maxProfit(k: Int, prices: IntArray): Int = prices.fold(
        Array(
            min(
                k,
                prices.size / 2
            ) + 1
        ) { -1000 to 0 }) { arr, v ->
        arr.apply {
            (1..arr.lastIndex).forEach { i ->
                arr[i] = max(arr[i].first, arr[i - 1].second - v) to max(arr[i].second, arr[i].first + v)
            }
        }
    }.last().second
}

一刀流

def maxProfit(k: Int, prices: Array[Int]): Int = prices.foldLeft(Array.fill(math.min(k, prices.length / 2) + 1)(-1000 -> 0)) { (acc, v) => (1 until acc.length).foreach(i => acc(i) = math.max(acc(i)._1, acc(i - 1)._2 - v) -> math.max(acc(i)._2, acc(i)._1 + v)); acc }.last._2
object Solution {
  def maxProfit(k: Int, prices: Array[Int]): Int =
    prices.foldLeft(Array.fill(math.min(k, prices.length / 2) + 1)(-1000 -> 0)) { (acc, v) =>
      (1 until acc.length).foreach(i =>
        acc(i) = math.max(acc(i)._1, acc(i - 1)._2 - v) -> math.max(acc(i)._2, acc(i)._1 + v))
      acc
    }.last._2
}

一刀流

pub fn max_profit(k: i32, prices: Vec<i32>) -> i32 {prices.iter().fold(vec![(-1000, 0); (k as usize).min(prices.len() / 2) + 1],|mut acc, v| {(1..acc.len()).for_each(|i| acc[i] = (acc[i].0.max(acc[i - 1].1 - v), acc[i].1.max(acc[i].0 + v)));acc},).last().unwrap().1}
impl Solution {
    pub fn max_profit(k: i32, prices: Vec<i32>) -> i32 {
        prices
            .iter()
            .fold(
                vec![(-1000, 0); (k as usize).min(prices.len() / 2) + 1],
                |mut acc, v| {
                    (1..acc.len()).for_each(|i| {
                        acc[i] = (acc[i].0.max(acc[i - 1].1 - v), acc[i].1.max(acc[i].0 + v))
                    });
                    acc
                },
            )
            .last()
            .unwrap()
            .1
    }
}