线性dp:最长上升子序列

news/2024/9/20 2:57:23/文章来源:https://www.cnblogs.com/Tomorrowland/p/18369763

最长上升子序列

  • 本文与leetcode300.最长递增子序列,这题题意一样,阅读完本文可以挑战一下

力扣链接

题目叙述:

给定一个无序的整数数组,找出其中最长上升子序列(LIS)的长度。

输入:

[5,7,1,9,4,6,2,8,3]

输出

4

解释

  • 最长上升子序列是[1,4,6,8],其长度为4。

动态规划的设计:

  • 首先,我们对数组进行下标的映射,我们从下标为1的位置开始计数

  • 并且,我们计算以每一个元素a【i】为结尾的最长上升子序列的长度f【i】。

img

  • 由上面这张图我们可知,最长的上升子序列可以由前面的状态推出,因此我们可以考虑使用动态规划算法

状态变量dp的含义:

  • 我们在这里数组名用f,而不用dp
  • f[i]代表以a[i]为结尾的最长上升子序列长度
  • 初始条件为f[i]=1

递推公式:

  • 我们需要一个j指针,每次遍历到a【i】时,我们都需要j指针,从1开始移动,移动到i-1的位置,如果发现a[i]>a[j],那么我们就更新f【i】的值,不过还得判断一下f【j】+1与f【i】的大小关系。
for(int i=2;i<=n;i++){for(int j=1;j<i;j++){if(a[i]>a[j]) f[i]=max(f[i],f[j]+1);}//ans为最终的最大上升子序列的长度ans=max(ans,f[i]);
}

遍历顺序:

  • 因为我们的状态变量f[i]是由f[j]决定的,所以说我们的遍历顺序显然是从前向后遍历

如何初始化?

  • 在上面已经说了:f[i]=1,因为每个数字至少都有以本身为序列的最长上升子序列。

举例打印dp数组

  • 下标 :1,2,3,4,5,6,7,8,9

  • a【i】:5,7,1,9,4,6,2,8,3

  • f【i】 :1,2,1,3,2,3,2,4,3

递推式满足的条件

  • 由小推大(最优子结构)
  • 由过去推现在(无后效性)

疑问:

  • f【i】记录以a【i】为开头的最长上升子序列可以吗?——可以,不过遍历顺序就是从后向前遍历,递推式也需要改变改变,这里读者可以自行推理!
  • f【i】记录前i个数的最长上升子序列的长度,可以吗?——不可以,举例两个就可以发现明显错误的反例,因此不成立。

代码实现:

#include <iostream>
#include <cstring>
#include <algorithm>using namespace std;
const int N=1010;
int n, a[N];
int f[N];int main(){cin>>n;for(int i=1; i<=n; i++) cin>>a[i];for(int i=1; i<=n; i++) f[i]=1;for(int i=1; i<=n; i++)for(int j=1; j<i; j++)if(a[j]<a[i]) f[i]=max(f[i],f[j]+1);int res=0;for(int i=1; i<=n; i++) res=max(res,f[i]);cout<<res;
}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Day01 Uboot编译

一. 安装环境1. 安装依赖sudo apt-get install gcc make cmake rsync wget unzip build-essential git bc swig libncurses5-dev libpython3-dev libssl-dev python3-distutils android-tools-mkbootimg -y   2. 安装编译器wget http://releases.linaro.org/components/toolc…

三维模型单体化软件:地理信息与遥感领域的精细化革命

在地理信息与遥感科学日新月异的发展浪潮中,单体化软件作为一股强大的驱动力,正引领着我们迈向空间信息处理与应用的新纪元。本文旨在深度解析单体化软件的核心价值、技术前沿、实践应用及面临的挑战,共同探讨这一技术如何塑造行业的未来。单体化软件:精细化时代的钥匙单体…

EasyExcel文档

源自官方文档,仅供我个人使用,其他人请移步官方地址:https://easyexcel.opensource.alibaba.com/,官方文档更详细更好!! 新手必读官方网站:https://easyexcel.opensource.alibaba.com/ github地址:https://github.com/alibaba/easyexcel gitee地址:https://gitee.com/…

在VS Code中使用Snippet Craft扩展提高编码效率

Snippet Craft 一个VS Code代码片段管理插件 功能 创建和插入代码片段 在编辑器区域右键菜单中点击插入Snippet,或在代码片段视图中点击条目,则会将代码片段插入到当前激活文档的光标位置。代码片段编辑 代码片段在左侧栏中,根据创建时的文件内容类型,分组显示代码片段,可…

cmake Makefile面试问题

摘自:https://wenku.baidu.com/view/4db705bdba0d6c85ec3a87c24028915f814d8462.html?_wkts_=1724332395577&bdQuery=cmake+%E9%9D%A2%E8%AF%95%E9%A2%98

Modern CMake 简介

摘自:https://zhuanlan.zhihu.com/p/76975231 Modern CMake 简介历史背景CMake是一个构建系统生成器(build-system generator)。常见的构建系统,有Visual Studio,XCode,Make等等。CMake可以支持不同平台下构建系统的生成。 CMake的出现已经有接近20年的历史,它的发展过程…

048、Vue3+TypeScript基础,基本的子页面和父页面相互通讯

01、main.js代码如下:// 引入createApp用于创建Vue实例 import {createApp} from vue // 引入App.vue根组件 import App from ./App.vueconst app = createApp(App);// App.vue的根元素id为app app.mount(#app)02、App.vue代码如下:<template><div class="app&…

1、拟合、预测、估算器、管道与模型评估

一、拟合和预测:估算器基础 1.1 资源导入、样本定义和训练from sklearn.ensemble import RandomForestClassifier #随机森林分类器 """ random_state=0 将使用固定的随机数种子(在这个例子中是0)来初始化随机数生成器。 这样,无论你的代码运行多少次,只要…

DDD精粹速读(一)

1 你需要知道的 - 战略设计 DDD是一种软件设计和构建方法,其重点在于独立于数据持久化等技术问题,准确表达业务规则。 不幸,DDD 对新手来说极具挑战性,部分原因是它有许多独特的概念需要学习。本文我简要介绍这些重要的思想,以便你能自信继续你的 DDD 旅程。 第一部分将侧…

消息队列作用(解耦、异步、削峰)

原文:消息队列作用(解耦、异步、削峰)图详解一、消息队列简介 简单来说,“消息队列”是在消息的传输过程中保存消息的容器。MQ 全称为 Message Queue,消息队列(MQ)是一种应用程序对应用程序的通信方法。应用程序通过读写出入队列的消息(针对应用程序的数据)来通信。 消…

C++ 链表

1. 前言 链表:不仅存储 当前元素的数据,还存储着 元素排列顺序 2. 正题 2.1 如何存储节点? 我们可以使用 结构体 数组来存储 链表节点 struct Node {int val; // 可以是 string 或其它复杂的类型int nxt; } node[N];Tip: 下标顺序不是单链表顺序val 代表 元素本身,nxt 代表…

WPF 模拟UWP原生窗口样式——亚克力|云母材质、自定义标题栏样式、原生DWM动画 (附我封装好的类)

先看一下最终效果,左图为使用亚克力材质并添加组合颜色的效果;右图为MicaAlt材质的效果。两者都自定义了标题栏并且最大限度地保留了DWM提供的原生窗口效果(最大化最小化、关闭出现的动画、窗口阴影、拖拽布局器等)。接下来把各部分的实现一个个拆开来讲讲。 一、使用窗口材…