力扣75——多维动态规划

news2024/9/24 23:32:16

总结leetcode75中的多维动态规划算法题解题思路。
上一篇:力扣75——一维动态规划

力扣75——多维动态规划

  • 1 不同路径
  • 2 最长公共子序列
  • 3 买卖股票的最佳时机含手续费
  • 4 编辑距离
  • 1 - 4 解题总结

1 不同路径

题目:

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。

问总共有多少条不同的路径?

题解:
动态规划。想要计算[m - 1][n - 1],需要计算[m - 2][n - 1][m - 1][n - 2]。从[0][0]开始递推即可。

class Solution {
public:
	int uniquePaths(int m, int n) {
		vector<vector<int>> results(m,vector<int>(n,1));
		for (int i = 1; i < m; i++) {
			for (int j = 1; j < n; j++) {
				results[i][j] = results[i - 1][j] + results[i][j - 1];
			}
		}
		return results[m - 1][n - 1];
	}
};

2 最长公共子序列

题目:

给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在
公共子序列 ,返回 0 。

一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情
况下删除某些字符(也可以不删除任何字符)后组成的新字符串。

例如,"ace""abcde" 的子序列,但 "aec" 不是 "abcde" 的子序列。
两个字符串的 公共子序列 是这两个字符串所共同拥有的子序列。

题解:
动态规划。下图为官方的说明。
在这里插入图片描述

class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {
        int m = text1.length(), n = text2.length();
        vector<vector<int>> dp(m + 1, vector<int>(n + 1));
        for (int i = 1; i <= m; i++) {
            char c1 = text1.at(i - 1);
            for (int j = 1; j <= n; j++) {
                char c2 = text2.at(j - 1);
                if (c1 == c2) {
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                } else {
                    dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
                }
            }
        }
        return dp[m][n];
    }
};

3 买卖股票的最佳时机含手续费

题目:

给定一个整数数组 prices,其中 prices[i]表示第 i 天的股票价格 ;整数 fee 代表了
交易股票的手续费用。

你可以无限次地完成交易,但是你每笔交易都需要付手续费。如果你已经购买了一个股票,
在卖出它之前你就不能再继续购买股票了。

返回获得利润的最大值。
注意:这里的一笔交易指买入持有并卖出股票的整个过程,每笔交易你只需要为支付一次手续费。

 

题解:
贪心。将手续费计算在买入的时候。
当买入时,将价格prices[i]和费用fee求和存于buy。
如果遇到价格prices[j]+fee低于buy,则得买这一天的,更新下buy。
如果遇到价格prices[k]高于buy,则可以得卖出。但这个卖出的时刻不一定是最佳的,所以需要将prices[k]存入buy,如果遇到更大的prices[l],则在这一天卖更好。

待证明的一点:如果遇到高于buy的prices[k],然后再遇到prices[m],它小于prices[k]但大于prices[k]-fee,此时是未买入的,这是否合理?
证明:如下图两种情况。第一种:如果存在prices[m],然后prices又继续往上升,则按算法逻辑会更新卖出时刻,改为在第二个峰值点卖出。第二种:如果存在prices[m],然后就再也没有超过prices[k]的值,则再次买入是不合理的,因为不管怎么交易的价格差异都小于fee,赚不到钱。
在这里插入图片描述

class Solution {
public:
    int maxProfit(vector<int>& prices, int fee) {
        int n = prices.size();
        int buy = prices[0] + fee;
        int profit = 0;
        for (int i = 1; i < n; ++i) {
            if (prices[i] + fee < buy) {
                buy = prices[i] + fee;
            }
            else if (prices[i] > buy) {
                profit += prices[i] - buy;
                buy = prices[i];
            }
        }
        return profit;
    }
};

4 编辑距离

题目:

给你两个单词 word1 和 word2, 请返回将 word1 转换成 word2 所使用的最少操作数  。

你可以对一个单词进行如下三种操作:
插入一个字符
删除一个字符
替换一个字符

题解:
这道题的阶梯思路与题目2相似,但更困难,下图为评论区@自底向上和自顶向下的解释。
在这里插入图片描述

class Solution {
public:
    int minDistance(string word1, string word2) {
        int n = word1.length();
        int m = word2.length();

        // 有一个字符串为空串
        if (n * m == 0) return n + m;

        // DP 数组
        vector<vector<int>> D(n + 1, vector<int>(m + 1));

        // 边界状态初始化
        for (int i = 0; i < n + 1; i++) {
            D[i][0] = i;
        }
        for (int j = 0; j < m + 1; j++) {
            D[0][j] = j;
        }

        // 计算所有 DP 值
        for (int i = 1; i < n + 1; i++) {
            for (int j = 1; j < m + 1; j++) {
                int left = D[i - 1][j] + 1;//删除
                int down = D[i][j - 1] + 1;//插入
                int left_down = D[i - 1][j - 1];//修改
                if (word1[i - 1] != word2[j - 1]) left_down += 1;
                D[i][j] = min(left, min(down, left_down));

            }
        }
        return D[n][m];
    }
};

1 - 4 解题总结

题3用贪心解题更容易。
多维动态规划题目特点:位置信息一般是2维,所以用于递推迭代保存状态信息的不再是一维vector,而是二维的vector。
优化点:与一维动态规划将vector优化为几个变量想通,可以将二维的vector优化成几个一维的vector。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/890263.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

史上最全!80个数字化工厂常见术语合集,看完秒懂~

这几天&#xff0c;有几个朋友私信我&#xff0c;问了我不少问题&#xff0c;其中有一个让我讲一讲“数字化工厂”方面的知识&#xff0c;了解我的人想必都清楚&#xff0c;我这个人一般都是有求必应的。 所以今天来聊一聊“数字化工厂”的常见术语&#xff0c;帮助大家快速搞…

【Linux】模拟实现linux的shell

#include <stdio.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <sys/wait.h> #include <sys/types.h> #define NUM 1024 #define SIZE 32 #define SEP " " int main() {//保存输入后的字符串char …

你需要需求管理解决方案的三个原因

我们最近研究了一份 Forrester Research 的报告&#xff0c;得出如下结论&#xff1a;高度监管的行业可以从敏捷需求管理方法中受益。在本文中&#xff0c;我们将深入探讨所有行业的客户如何从一个协作平台中受益&#xff0c;该平台如何帮助他们在复杂的开发周期中管理需求。 …

【傅里叶级数与傅里叶变换】数学推导——3、[Part4:傅里叶级数的复数形式] + [Part5:从傅里叶级数推导傅里叶变换] + 总结

文章内容来自DR_CAN关于傅里叶变换的视频&#xff0c;本篇文章提供了一些基础知识点&#xff0c;比如三角函数常用的导数、三角函数换算公式等。 文章全部链接&#xff1a; 基础知识点 Part1&#xff1a;三角函数系的正交性 Part2&#xff1a;T2π的周期函数的傅里叶级数展开 P…

工作流引擎之Flowable教程(整合SpringBoot)

简介 Flowable是什么&#xff0c;下面是官方文档介绍&#xff1a; Flowable是一个使用Java编写的轻量级业务流程引擎。Flowable流程引擎可用于部署BPMN 2.0流程定义&#xff08;用于定义流程的行业XML标准&#xff09;&#xff0c; 创建这些流程定义的流程实例&#xff0c;进行…

C++新经典04--位运算

背景 许多网络游戏为了刺激玩家每天上线&#xff0c;都在游戏中设有“每日任务”——每天让玩家做一些任务&#xff0c;如杀怪、采集来赚取积分、金钱、经验等。每日任务根据游戏不同&#xff0c;数量也不同&#xff0c;每日任务比较少的网络游戏中&#xff0c;可能每日任务只…

多语言多模态(融合图像和文本)大模型-mPLUG-Owl论文解读

近期复现了mPLUG-Owl&#xff0c;效果提升了好几个点&#xff0c;特来精读一番&#xff1a;感谢大佬们的工作&#xff1a; 论文名称&#xff1a;mPLUG-Owl: Modularization Empowers Large Language Models with Multimodality 论文地址&#xff1a;https://arxiv.org/pdf/23…

使用GUI Guider工具开发嵌入式GUI应用(5)-使用timer对象显示动画

使用GUI Guider工具开发嵌入式GUI应用&#xff08;5&#xff09;-使用timer对象显示动画 文章目录 使用GUI Guider工具开发嵌入式GUI应用&#xff08;5&#xff09;-使用timer对象显示动画引言LVGL中的timer对象基于timer对象实现仪表走针小结 引言 设计GUI的显示元素动起来&a…

Websocket原理和实践

一、概述 1.websocket是什么&#xff1f; WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket使得客户端和服务器之间的数据交换变得更加简单&#xff0c;允许服务端主动向客户端推送数据。在WebSocket API中&#xff0c;浏览器和服务器只需要完成一次握手&…

如何快速优化 CnosDB 数据库性能与延迟:使用 Jaeger 分布式追踪系统

在正式的生产环境中&#xff0c;数据库的性能和延迟对于确保系统的稳定和高效运行至关重要。特别是在与 CnosDB 数据库进行交互时&#xff0c;更深入地了解其表现变得尤为重要。这时Jaeger 分布式追踪系统发挥了巨大的作用。在本篇博客中&#xff0c;我们将深入探讨如何通过使用…

ATA-4000系列高压功率放大器——应用场景介绍

ATA-4000系列是一款理想的可放大交、直流信号的高压功率放大器。最大输出310Vp-p(155Vp)电压&#xff0c;452Wp功率&#xff0c;可以驱动高压功率型负载。电压增益&#xff0c;直流偏置数控精细可调&#xff0c;为客户提供了丰富的测试选择。 图&#xff1a;ATA-4000系列高压功…

ndk开发-交叉编译

为什么要使用交叉编译&#xff1a; 在linux系统一般使用c c编译可执行程序或者so库文件。该程序只能在当前linux系统执行&#xff0c;为了将生成文件可以再android平台运行&#xff0c;必须使用交叉编译。ndk中提供了跟多android平台交叉编译链&#xff0c;所以首先下载ndk工具…

FPGA应用学习笔记-----布图布线

分割可以将运行时间惊人地减少到三个小时更小的布局布线操作&#xff0c;主要的结构不影响另一个&#xff01;和增量设计流程一样 关键路径布图&#xff1a; 对于不同的模块有不同的电路和不同的关键路径&#xff0c; 布图没有主要的分割&#xff0c;布图由两个小的区域组成&a…

KDD 2023 获奖论文公布,港中文、港科大等获最佳论文奖

ACM SIGKDD&#xff08;国际数据挖掘与知识发现大会&#xff0c;KDD&#xff09;是数据挖掘领域历史最悠久、规模最大的国际顶级学术会议&#xff0c;也是首个引入大数据、数据科学、预测分析、众包等概念的会议。 今年&#xff0c;第29届 KDD 大会于上周在美国加州长滩圆满结…

C语言入门教程,C语言学习教程(非常详细)第五章 循环结构与选择结构

C语言if else语句详解 前面我们看到的代码都是顺序执行的&#xff0c;也就是先执行第一条语句&#xff0c;然后是第二条、第三条……一直到最后一条语句&#xff0c;这称为顺序结构。 但是对于很多情况&#xff0c;顺序结构的代码是远远不够的&#xff0c;比如一个程序限制了只…

【Javaswing课设源码】学生信息管理 Mysql课程设计 管理员 教师 学生

文章目录 系统介绍 系统介绍 大学时代弄的一个课设&#xff0c;当时百度[学长敲代码]找的代做&#xff0c;代码思路很清晰&#xff0c;完全按照我的功能需求去做的&#xff0c;主要是价格便宜&#xff0c;真的爱了&#xff0c;现在回头学习也是不错的一个项目。大概内容如下 本…

springboot里 用zxing 生成二维码

引入pom <!--二维码依赖--><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.3.3</version></dependency><dependency><groupId>com.google.zxing</groupId>…

【分类讨论】CF1674 E

Problem - E - Codeforces 题意&#xff1a; 思路&#xff1a; 样例&#xff1a; 这种分类讨论的题&#xff0c;主要是去看答案的最终来源是哪几种情况&#xff0c;这几种情况得不重不漏 Code&#xff1a; #include <bits/stdc.h>#define int long longusing i64 lon…

尚硅谷css3笔记

目录 一、新增长度单位 二、新增盒子属性 1.border-box 怪异盒模型 2.resize 调整盒子大小 3.box-shadow 盒子阴影 案例&#xff1a;鼠标悬浮盒子上时&#xff0c;盒子有一个过度的阴影效果 三、新增背景属性 1.background-origin 设置背景图的原点 2.background-clip 设置背…

基于IMX6ULLmini的linux裸机开发系列一:汇编点亮LED

思来想去还是决定记录一下点灯&#xff0c;毕竟万物皆点灯嘛 编程步骤 使能GPIO时钟 设置引脚复用为GPIO 设置引脚属性(上下拉、速率、驱动能力) 控制GPIO引脚输出高低电平 使能GPIO时钟 其实和32差不多 先找到控制LED灯的引脚&#xff0c;也就是原理图 文件名 C:/Us…