【LeetCode】P300 最长上升子序列(未完结)

news/2024/10/18 8:32:19/

P300 最长上升子序列

文章目录

  • P300 最长上升子序列
    • 题目描述
    • 题解
      • 方法一:动态规划
      • 方法二:贪心 + 二分查找

题目链接:300. 最长上升子序列.

题目描述

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

示例:

输入: [10,9,2,5,3,7,101,18]
输出: 4
解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。

说明:

  • 可能会有多种最长上升子序列的组合,你只需要输出对应的长度即可。
  • 你算法的时间复杂度应该为 O ( n 2 ) O(n^2) O(n2)

进阶: 你能将算法的时间复杂度降低到 O ( n log ⁡ n ) O(n\log n) O(nlogn) 吗?

题解

方法一:动态规划

链接:动态规划.

思路

  • ①将原问题分解为子问题

“求序列的前 i i i 个元素的最长上升子序列的长度”是个子问题,但这样分解子问题,不具有“无后效性”的特点。

定义 d p [ i ] = x dp[i]=x dp[i]=x 为前 i i i 个元素( n u m s [ 0 ] 、 n u m s [ 1 ] … n u m s [ i − 1 ] nums[0]、nums[1] … nums[i-1] nums[0]nums[1]nums[i1])的最长上升子序列的长度为 x x x,但在这前 i i i 个元素中,可能有多个上升子序列同时满足 d p [ i ] = x dp[i]=x dp[i]=x。有的子序列的最后一个元素比 n u m s [ i ] nums[i] nums[i] 小,则加上 n u m s [ i ] nums[i] nums[i] 就能形成更长的上升子序列;有的序列最后一个元素不比 n u m s [ i ] nums[i] nums[i] 小,不能加上 n u m s [ i ] nums[i] nums[i] 形成更长的上升子序列。所以在当前的若干个状态值确定后,此后的过程演变不仅与这若干个状态的值有关,而且与之前经过哪条路径演变到当前这个状态有关,在本题中即: d p [ i + 1 ] dp[i+1] dp[i+1] 不仅与 d p [ i ] dp[i] dp[i] 有关,而且与在前 i i i 个元素中选择哪条最长上升子序列的最后一个元素与 n u m s [ i ] nums[i] nums[i] 进行比较有关。

子问题:“求以元素 n u m s [ i ] nums[i] nums[i] i = 0 、 1 、 2... n − 1 i=0、1、2 ... n-1 i=012...n1 n n n 为数组 n u m s nums nums 中元素个数)为终点的最长上升子序列的长度”。定义 d p [ i ] dp[i] dp[i] 为以元素 n u m s [ i ] nums[i] nums[i]为终点的最长上升子序列的长度,共有 n n n 个子问题,将这 n n n 个子问题都解决了,那最大解就是原问题的解了,这就满足了问题具有最优子结构性质

  • ②确定状态

子问题只与一个变量有关:元素下标 i i i,所以每个子问题中最长上升子序列的终点元素的下标 i i i,就是状态,而状态 i i i 对应的值就是以元素 n u m s [ i ] nums[i] nums[i] 为终点的最长上升子序列的长度,所以我们只用一个一维数组就可以存储各个状态的值。共有 n n n 个状态,它们构成状态空间。

  • ③确定一些边界状态(初始状态)的值

显然,以元素 n u m s [ 0 ] nums[0] nums[0] 为终点的最长上升子序列的长度为 1 1 1,所以有 d p [ 0 ] = 1 dp[0]=1 dp[0]=1

  • ④确定状态转移方程

在计算 d p [ i ] dp[i] dp[i] 时,我们假设已经将 d p [ 0 ] 、 d p [ 1 ] 、 d p [ i − 1 ] dp[0]、dp[1]、dp[i-1] dp[0]dp[1]dp[i1] 都已经计算出来了,那么要计算 d p [ i ] dp[i] dp[i] 的值就要先在 d p [ 0 ] 、 d p [ 1 ] . . . d p [ i − 1 ] dp[0]、dp[1] ... dp[i-1] dp[0]dp[1]...dp[i1] 中寻找 d p [ j ] dp[j] dp[j] 0 ⩽ j ⩽ i − 1 , j ∈ Z 0\leqslant j\leqslant i-1,j\in \mathbb{Z} 0ji1jZ), d p [ j ] dp[j] dp[j] 有:

d p [ j ] = max ⁡ ( d p [ k ] , k ∈ s e t ) , s e t = { k ∣ n u m s [ k ] < n u m s [ i ] ( 0 ⩽ k ⩽ i − 1 , k ∈ Z ) } dp[j]=\max(dp[k],k\in set),set=\{k|nums[k]<nums[i](0\leqslant k\leqslant i-1,k\in \mathbb{Z})\} dp[j]=max(dp[k]kset)set={knums[k]<nums[i](0ki1kZ)}

找到 d p [ j ] dp[j] dp[j] 后,则有 d p [ i ] = d p [ j ] + 1 dp[i]=dp[j]+1 dp[i]=dp[j]+1

也就是 d p [ i ] dp[i] dp[i] 的值为满足终点元素在 n u m s [ i ] nums[i] nums[i] 的左边、终点元素小于 n u m s [ i ] nums[i] nums[i] 的上升子序列中的最长上升子序列的长度加 1。

我们可以得到状态转移方程:
d p [ i ] = { max ⁡ ( d p [ k ] , k ∈ s e t ) + 1 s e t ≠ ∅ 1 s e t = ∅ dp[i] = \begin{cases} \max(dp[k],k\in set)+1 &set\neq \varnothing \\ 1 &set=\varnothing \end{cases} dp[i]={max(dp[k]kset)+11set=set=

s e t = { k ∣ n u m s [ k ] < n u m s [ i ] ( 0 ⩽ k ⩽ i − 1 , k ∈ Z ) } set=\{k|nums[k]<nums[i](0\leqslant k\leqslant i-1,k\in \mathbb{Z})\} set={knums[k]<nums[i](0ki1kZ)}

状态转移方程是递推形式的,所以在计算 d p [ i ] dp[i] dp[i] 时,我们已经将 d p [ 0 ] 、 d p [ 1 ] 、 d p [ i − 1 ] dp[0]、dp[1]、dp[i-1] dp[0]dp[1]dp[i1] 都已经计算出来了。

  • 原问题的解

最后,整个数组的最长上升子序列的长度 m a x L e n maxLen maxLen 即数组 d p dp dp 中的最大值。
m a x L e n = max ⁡ ( d p [ i ] ) , ( 0 ⩽ i ⩽ n − 1 , i ∈ Z ) maxLen=\max(dp[i]),(0\leqslant i\leqslant n-1,i\in \mathbb{Z}) maxLen=max(dp[i])(0in1iZ)

算法

class Solution {
public:int lengthOfLIS(vector<int>& nums) {if(nums.size()==0){return 0;}int size=nums.size();vector<int> dp(size,1);int maxLen=dp[0];for(int i=1;i<size;++i){int temp=1;for(int j=0;j<i;++j){if(nums[i]>nums[j]){temp=dp[j]+1>temp?dp[j]+1:temp;}}dp[i]=temp;maxLen=dp[i]>maxLen?dp[i]:maxLen;}return maxLen;}
};

复杂度分析

假设数组中元素的个数为 n n n

  • 时间复杂度: O ( n 2 ) O(n^2) O(n2),因为动态规划中状态的数目为 n n n,在计算状态 i i i 的值 d p [ i ] dp[i] dp[i] 时需要遍历 d p [ 0 ] 、 d p [ 1 ] . . . d p [ i − 1 ] dp[0]、dp[1]...dp[i-1] dp[0]dp[1]...dp[i1],时间复杂度为 O ( n ) O(n) O(n),由动态规划解题的时间复杂度计算公式:
    时 间 复 杂 度 = 状 态 的 数 目 ⋅ 计 算 每 个 状 态 所 需 时 间 时间复杂度=状态的数目⋅计算每个状态所需时间 =所以得到时间复杂度 O ( n 2 ) O(n^2) O(n2)
  • 空间复杂度: O ( n ) O(n) O(n),需要一个长度为 n n n 一维数组 d p dp dp 来存储各个状态的值。

方法二:贪心 + 二分查找

思路

算法

复杂度分析


http://www.ppmy.cn/news/327742.html

相关文章

mne脑机接口:对P300数据集的研究与模式识别(代码复用)

2023/3/1-2023/3/4 脑机接口学习内容一览&#xff1a; 这一篇博客里&#xff0c;将对来自于kaggle的P300数据集&#xff08;P300-Dataset&#xff09;开展研究&#xff0c;并且简化了任务流程&#xff0c;从识别P300电位对应字符到识别是否出现P300电位&#xff0c;因此准确率较…

基于BCIduino脑电模组和OpenVibe的P300意念打字系统搭建

在现实生活中&#xff0c;有很多思维正常但是有运动障碍的人无法直接与外界进行沟通。随着脑电技术的发展&#xff0c;脑机接口逐渐成为他们与外界的潜在交流方式&#xff0c;其特点在于直接通过大脑可以控制外设及字符输出等&#xff0c;不用借助外周肌肉组织等。在脑机接口领…

matlab实现rte接口_脑机接口P300信号处理(MATLAB实现)

学号&#xff1a;17020150056 姓名&#xff1a;张伟航 【嵌牛导读】事件相关电位(Event-related potentials, ERP)是大脑对某种事件进行信息加工时诱发产生的一系列电活动。其中&#xff0c;P300电位是一种内源性的事件相关电位&#xff0c;与认知功能相关的&#xff0c;对概…

混合SSVEP-P300 BCI生产双频SSVEP

目录 简介实验与结果结论 本分享为脑机学习者Rose整理发表于公众号&#xff1a;脑机接口社区 .QQ交流群&#xff1a;903290195 简介 首尔国立首尔大学医学院的科研人员介绍了一种新的混合SSVEP- P300 拼写器(speller)&#xff0c;该拼写器能够产生双频SSVEP&#xff0c;在解…

App 软件开发《填空2》试卷及答案

App 软件开发《填空2》试卷及答案 文章目录 App 软件开发《填空2》试卷及答案填空题&#xff08;共计0分&#xff09;1&#xff0e;ionic中缩略图是比头像大的正方形的图片&#xff0c;被定义为【80】px大小2&#xff0e;ionic中使用.【card】类来定义展示内容的卡片&#xff0…

关于事件相关电位P300应用于视频游戏的研究

事件相关电位 ERP 事件相关电位(ERP)是由大脑产生的与特定内部或外部事件(如刺激、反应、决策)相关的电位。它们可以提供关于广泛的认知和情感过程的信息。ERP为我们提供了对感觉和认知过程的洞察。事件相关电位很多&#xff0c;通常被称为ERP组件。 在最常见的ERP命名约定中&a…

python脑电信号分析_P300脑电信号的特征提取及分类研究

龙源期刊网 http://www.qikan.com.cn P300 脑电信号的特征提取及分类研究 作者:马也 姜光萍 来源:《山东工业技术》 2017 年第 10 期 摘 要:针对 P300 脑电信号信噪比低,分类困难的特点,本文研究了一种基于独立分量分 析和支持向量机相结合的脑电信号处理方法。首先对 P30…

python信号降噪_EEG(P300)信号数据滤波降噪

我有大量的脑电图数据(20000)&#xff0c;我把它们转换成P300(每1000个原始数据的平均值代表1个P300)。(我用了Python) 我的问题是减少噪音。我删减了30%的数据&#xff0c;因为P300信号在300毫秒后开始可见。但是&#xff0c;在我的数据中有噪音。我想用过滤器去除我的噪音。在…