算法学习第十六天:动态规划(补充题目)

动态规划题

目录

  1. 最大乘积子数组
  2. 股票买卖问题
  3. 最长递增子序列
  4. 零钱兑换
  5. 编辑距离

最大乘积子数组

问题描述

给定一个整数数组,求乘积最大的连续子数组的乘积。

关键点

  • 需要同时记录当前最大值和最小值(负负得正)
  • 状态转移方程:
    • max_dp[i] = max(nums[i], max_dp[i-1]*nums[i], min_dp[i-1]*nums[i])
    • min_dp[i] = min(nums[i], max_dp[i-1]*nums[i], min_dp[i-1]*nums[i])

C++代码

cpp 复制代码
int maxProduct(vector<int>& nums) {
    int max_val = nums[0], min_val = nums[0], res = nums[0];
    for (int i = 1; i < nums.size(); ++i) {
        int tmp_max = max({nums[i], max_val * nums[i], min_val * nums[i]});
        int tmp_min = min({nums[i], max_val * nums[i], min_val * nums[i]});
        max_val = tmp_max;
        min_val = tmp_min;
        res = max(res, max_val);
    }
    return res;
}

股票买卖问题

通用动态规划思路

  • 状态定义 :dp[i][k][0/1] 表示第i天,最多交易k次,是否持有股票时的最大利润。
  • 状态转移 :
    • dp[i][k][0] = max(dp[i-1][k][0], dp[i-1][k][1] + prices[i])
    • dp[i][k][1] = max(dp[i-1][k][1], dp[i-1][k-1][0] - prices[i])

交易一次(LeetCode 121)

cpp 复制代码
int maxProfit(vector<int>& prices) {
    int buy = INT_MIN, sell = 0;
    for (int price : prices) {
        buy = max(buy, -price);
        sell = max(sell, buy + price);
    }
    return sell;
}

交易无限次(LeetCode 122)

cpp 复制代码
int maxProfit(vector<int>& prices) {
    int profit = 0;
    for (int i = 1; i < prices.size(); ++i)
        if (prices[i] > prices[i-1])
            profit += prices[i] - prices[i-1];
    return profit;
}

交易两次(LeetCode 123)

cpp 复制代码
int maxProfit(vector<int>& prices) {
    int buy1 = INT_MIN, sell1 = 0, buy2 = INT_MIN, sell2 = 0;
    for (int price : prices) {
        buy1 = max(buy1, -price);
        sell1 = max(sell1, buy1 + price);
        buy2 = max(buy2, sell1 - price);
        sell2 = max(sell2, buy2 + price);
    }
    return sell2;
}

最长递增子序列

动态规划(O(n²))

cpp 复制代码
int lengthOfLIS(vector<int>& nums) {
    vector<int> dp(nums.size(), 1);
    int res = 1;
    for (int i = 1; i < nums.size(); ++i) {
        for (int j = 0; j < i; ++j)
            if (nums[i] > nums[j])
                dp[i] = max(dp[i], dp[j] + 1);
        res = max(res, dp[i]);
    }
    return res;
}

贪心+二分(O(n log n))

cpp 复制代码
int lengthOfLIS(vector<int>& nums) {
    vector<int> lis;
    for (int num : nums) {
        auto it = lower_bound(lis.begin(), lis.end(), num);
        if (it == lis.end()) lis.push_back(num);
        else *it = num;
    }
    return lis.size();
}

零钱兑换

动态规划

  • 状态定义 :dp[i]表示凑出金额i所需的最少硬币数。
  • 状态转移 :dp[i] = min(dp[i], dp[i - coin] + 1)
cpp 复制代码
int coinChange(vector<int>& coins, int amount) {
    vector<int> dp(amount + 1, amount + 1);
    dp[0] = 0;
    for (int i = 1; i <= amount; ++i)
        for (int coin : coins)
            if (coin <= i)
                dp[i] = min(dp[i], dp[i - coin] + 1);
    return dp[amount] > amount ? -1 : dp[amount];
}

编辑距离

动态规划

  • 状态定义 :dp[i][j]表示将word1前i个字符转换为word2前j个字符的最小操作数。
  • 状态转移 :
    • 若word1[i-1] == word2[j-1]:dp[i][j] = dp[i-1][j-1]
    • 否则:dp[i][j] = 1 + min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1])
cpp 复制代码
int minDistance(string word1, string word2) {
    int m = word1.size(), n = word2.size();
    vector<vector<int>> dp(m+1, vector<int>(n+1, 0));
    for (int i = 0; i <= m; ++i) dp[i][0] = i;
    for (int j = 0; j <= n; ++j) dp[0][j] = j;
    
    for (int i = 1; i <= m; ++i)
        for (int j = 1; j <= n; ++j)
            if (word1[i-1] == word2[j-1])
                dp[i][j] = dp[i-1][j-1];
            else
                dp[i][j] = 1 + min({dp[i-1][j], dp[i][j-1], dp[i-1][j-1]});
    return dp[m][n];
}
相关推荐
jyyyx的算法博客12 分钟前
传球游戏【思维】
算法
星恒随风16 分钟前
Linux基础IO万字详解:从文件描述符fd到重定向、FILE缓冲机制及MiniShell升级
linux·运维·笔记·学习·状态模式
FL162386312921 分钟前
关于2026年南昌大学811信号与系统最后一题电路系统解题思路
算法
殷色玫瑰21 分钟前
C++ STL:map 与 set 详解——从底层红黑树到实际应用
c语言·数据结构·c++·算法·visualstudio·rpc
行者全栈架构师27 分钟前
【鸿蒙心迹】鸿蒙网络请求架构实战——@ohos.net.http 到 Axios 封装、拦截器与统一错误处理(HarmonyOS 7.x)
前端·算法·架构
小雪崩33 分钟前
嵌入式学习 day65:Linux驱动进阶——pinctrl 子系统和 platform 驱动框架
linux·学习·驱动
shixiexunnie37 分钟前
Raw NAND 驱动库学习
驱动开发·学习
小宋102142 分钟前
OpenTelemetry GenAI可观测性实战:串起模型、工具、Token与错误
java·人工智能·算法·贪心算法
嫂子开门我是_我哥43 分钟前
青少年抑郁、焦虑、失眠与自杀相关表现的症状联系:一篇网络分析论文所使用的算法深度解读
论文阅读·算法·论文笔记
喜欢打篮球的普通人1 小时前
MiniMind 学习笔记(二十二):数学 Cookbook——把概率空间、期望、似然一次讲明白
人工智能·笔记·学习