Leetcode376. 摆动序列

Every day a Leetcode

题目来源:376. 摆动序列

解法1:动态规划

约定:

  1. 某个序列被称为「上升摆动序列」,当且仅当该序列是摆动序列,且最后一个元素呈上升趋势。
  2. 某个序列被称为「下降摆动序列」,当且仅当该序列是摆动序列,且最后一个元素呈下降趋势。
  3. 特别地,对于长度为 1 的序列,它既是「上升摆动序列」,也是「下降摆动序列」。
  4. 序列中的某个元素被称为「峰」,当且仅当该元素两侧的相邻元素均小于它。
  5. 序列中的某个元素被称为「谷」,当且仅当该元素两侧的相邻元素均大于它。
  6. 特别地,对于位于序列两端的元素,只有一侧的相邻元素小于或大于它,我们也称其为「峰」或「谷」。
  7. 对于序列中既非「峰」也非「谷」的元素,我们称其为「过渡元素」。

状态数组:

  1. up[i]:表示以前 i 个元素中的某一个为结尾的最长的「上升摆动序列」的长度。
  2. down[i]:表示以前 i 个元素中的某一个为结尾的最长的「下降摆动序列」的长度。

最终的状态转移方程为:

在这里插入图片描述

最终的答案即为 up[n−1] 和 down[n−1] 中的较大值,其中 n 是序列的长度。

代码:

/** @lc app=leetcode.cn id=376 lang=cpp** [376] 摆动序列*/// @lc code=start
class Solution
{
public:int wiggleMaxLength(vector<int> &nums){// 特判if (nums.size() <= 1)return nums.size();int n = nums.size();// 状态数组// up[i]:表示以前i个元素中的某一个为结尾的最长的「上升摆动序列」的长度vector<int> up(n + 1, 0);// down[i]:表示以前i个元素中的某一个为结尾的最长的「下降摆动序列」的长度vector<int> down(n + 1, 0);// 初始化// 对于长度为1的序列,它既是「上升摆动序列」,也是「下降摆动序列」up[1] = down[1] = 1;// 状态转移for (int i = 2; i <= n; i++){if (nums[i - 1] > nums[i - 2]){up[i] = max(up[i - 1], down[i - 1] + 1);down[i] = down[i - 1];}else if (nums[i - 1] < nums[i - 2]){up[i] = up[i - 1];down[i] = max(up[i - 1] + 1, down[i - 1]);}else{up[i] = up[i - 1];down[i] = down[i - 1];}}return max(up[n], down[n]);}
};
// @lc code=end

结果:

在这里插入图片描述

复杂度分析:

时间复杂度:O(n),其中 n 是序列的长度。我们只需要遍历该序列一次。

空间复杂度:O(n),其中 n 是序列的长度。我们需要开辟两个长度为 n 的数组。

空间优化

代码:

/** @lc app=leetcode.cn id=376 lang=cpp** [376] 摆动序列*/// @lc code=start// 动态规划// class Solution
// {
// public:
//     int wiggleMaxLength(vector<int> &nums)
//     {
//         // 特判
//         if (nums.size() <= 1)
//             return nums.size();
//         int n = nums.size();
//         // 状态数组
//         // up[i]:表示以前i个元素中的某一个为结尾的最长的「上升摆动序列」的长度
//         vector<int> up(n + 1, 0);
//         // down[i]:表示以前i个元素中的某一个为结尾的最长的「下降摆动序列」的长度
//         vector<int> down(n + 1, 0);
//         // 初始化
//         // 对于长度为1的序列,它既是「上升摆动序列」,也是「下降摆动序列」
//         up[1] = down[1] = 1;
//         // 状态转移
//         for (int i = 2; i <= n; i++)
//         {
//             if (nums[i - 1] > nums[i - 2])
//             {
//                 up[i] = max(up[i - 1], down[i - 1] + 1);
//                 down[i] = down[i - 1];
//             }
//             else if (nums[i - 1] < nums[i - 2])
//             {
//                 up[i] = up[i - 1];
//                 down[i] = max(up[i - 1] + 1, down[i - 1]);
//             }
//             else
//             {
//                 up[i] = up[i - 1];
//                 down[i] = down[i - 1];
//             }
//         }
//         return max(up[n], down[n]);
//     }
// };// 动态规划-空间优化class Solution
{
public:int wiggleMaxLength(vector<int> &nums){// 特判if (nums.size() <= 1)return nums.size();int n = nums.size();int up = 1, down = 1;// 状态转移for (int i = 1; i < n; i++){if (nums[i] > nums[i - 1])up = max(up, down + 1);else if (nums[i] < nums[i - 1])down = max(down, up + 1);}return max(up, down);}
};
// @lc code=end

结果:

在这里插入图片描述

解法2:贪心

观察这个序列可以发现,我们不断地交错选择「峰」与「谷」,可以使得该序列尽可能长。证明非常简单:如果我们选择了一个「过渡元素」,那么在原序列中,这个「过渡元素」的两侧有一个「峰」和一个「谷」。不失一般性,我们假设在原序列中的出现顺序为「峰」「过渡元素」「谷」。如果「过渡元素」在选择的序列中小于其两侧的元素,那么「谷」一定没有在选择的序列中出现,我们可以将「过渡元素」替换成「谷」;同理,如果「过渡元素」在选择的序列中大于其两侧的元素,那么「峰」一定没有在选择的序列中出现,我们可以将「过渡元素」替换成「峰」。这样一来,我们总可以将任意满足要求的序列中的所有「过渡元素」替换成「峰」或「谷」。并且由于我们不断地交错选择「峰」与「谷」的方法就可以满足要求,因此这种选择方法就一定可以达到可选元素数量的最大值。

这样,我们只需要统计该序列中「峰」与「谷」的数量即可(注意序列两端的数也是「峰」或「谷」),但需要注意处理相邻的相同元素。

在实际代码中,我们记录当前序列的上升下降趋势。每次加入一个新元素时,用新的上升下降趋势与之前对比,如果出现了「峰」或「谷」,答案加一,并更新当前序列的上升下降趋势。

代码:

/** @lc app=leetcode.cn id=376 lang=cpp** [376] 摆动序列*/// @lc code=start// 动态规划// class Solution
// {
// public:
//     int wiggleMaxLength(vector<int> &nums)
//     {
//         // 特判
//         if (nums.size() <= 1)
//             return nums.size();
//         int n = nums.size();
//         // 状态数组
//         // up[i]:表示以前i个元素中的某一个为结尾的最长的「上升摆动序列」的长度
//         vector<int> up(n + 1, 0);
//         // down[i]:表示以前i个元素中的某一个为结尾的最长的「下降摆动序列」的长度
//         vector<int> down(n + 1, 0);
//         // 初始化
//         // 对于长度为1的序列,它既是「上升摆动序列」,也是「下降摆动序列」
//         up[1] = down[1] = 1;
//         // 状态转移
//         for (int i = 2; i <= n; i++)
//         {
//             if (nums[i - 1] > nums[i - 2])
//             {
//                 up[i] = max(up[i - 1], down[i - 1] + 1);
//                 down[i] = down[i - 1];
//             }
//             else if (nums[i - 1] < nums[i - 2])
//             {
//                 up[i] = up[i - 1];
//                 down[i] = max(up[i - 1] + 1, down[i - 1]);
//             }
//             else
//             {
//                 up[i] = up[i - 1];
//                 down[i] = down[i - 1];
//             }
//         }
//         return max(up[n], down[n]);
//     }
// };// 动态规划-空间优化// class Solution
// {
// public:
//     int wiggleMaxLength(vector<int> &nums)
//     {
//         // 特判
//         if (nums.size() <= 1)
//             return nums.size();
//         int n = nums.size();
//         int up = 1, down = 1;
//         // 状态转移
//         for (int i = 1; i < n; i++)
//         {
//             if (nums[i] > nums[i - 1])
//                 up = max(up, down + 1);
//             else if (nums[i] < nums[i - 1])
//                 down = max(down, up + 1);
//         }
//         return max(up, down);
//     }
// };// 贪心class Solution
{
public:int wiggleMaxLength(vector<int> &nums){// 特判if (nums.size() <= 1)return nums.size();int n = nums.size();int preDiff = nums[1] - nums[0];int ans = preDiff != 0 ? 2 : 1;for (int i = 2; i < n; i++){int diff = nums[i] - nums[i - 1];if ((diff > 0 && preDiff <= 0) || (diff < 0 && preDiff >= 0)){ans++;preDiff = diff;}}return ans;}
};
// @lc code=end

结果:

在这里插入图片描述

复杂度分析:

时间复杂度:O(n),其中 n 是序列的长度。我们只需要遍历该序列一次。

空间复杂度:O(1)。我们只需要常数空间来存放若干变量。

第二种贪心思路:统计变化次数

代码:

// 贪心2class Solution
{
public:int wiggleMaxLength(vector<int> &nums){// 特判if (nums.size() <= 1)return nums.size();int n = nums.size();int direction = 0; //-1表示下降,1表示上升int count = 0;     // 变化次数for (int i = 1; i < n; i++){if (nums[i] > nums[i - 1]){if (direction != 1){direction = 1;count++;}}else if (nums[i] < nums[i - 1]){if (direction != -1){direction = -1;count++;}}}// 因为统计的是变化的次数,最终的结果是序列的长度,所以需要+1return count + 1;}
};

结果:

在这里插入图片描述

复杂度分析:

时间复杂度:O(n),其中 n 是序列的长度。我们只需要遍历该序列一次。

空间复杂度:O(1)。我们只需要常数空间来存放若干变量。

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

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

相关文章

基于粒子群优化的BP神经网络算法

大家好&#xff0c;我是带我去滑雪&#xff01; 基于粒子群优化的BP神经网络算法&#xff08;Particle Swarm Optimization Backpropagation Neural Network&#xff0c;PSO-BPNN&#xff09;是一种利用粒子群优化算法优化BP神经网络的算法。它将BP神经网络的权重和偏置值作为粒…

C++vector模拟实现

vector模拟实现 1.构造函数2.拷贝构造3.析构赋值运算符重载4.iterator5.modifiers5.1push_back5.2pop_back5.3empty5.4insert5.5erase5.6swap 6.Capacity6.1size6.2capacity6.3reserve6.4resize6.5empty 7.Element access7.1operator[]7.2at 8.在谈reserve vector官方库实现的是…

SQL11 高级操作符练习(1)

描述 题目&#xff1a;现在运营想要找到男性且GPA在3.5以上(不包括3.5)的用户进行调研&#xff0c;请你取出相关数据。 示例&#xff1a;user_profile iddevice_idgenderageuniversitygpa12138male21北京大学3.423214male复旦大学4.036543female20北京大学3.242315female23浙…

向量范数及其Python代码

【向量范数】 向量由于既有大小又有方向&#xff0c;所以不能直接比较大小。 向量范数通过将向量转化为实数&#xff0c;然后进行向量的大小比较。 所以&#xff0c;向量范数是用于度量“向量大小”的量。 设向量 &#xff0c;则有&#xff1a; ● 向量的 范数&#xff1a; ●…

Python计算机Python二级知识点整理

1. 此时我们这里首先解析一下这个d[A]N,根据ASCII表&#xff0c;我们可以看出字符A对应的十进制数字是65&#xff0c;ord()函数是把字符转换为相对应的ASCII码&#xff0c;chr()函数是ord()函数的逆运算&#xff0c;所以ord("A")65 ,chr(65)A,题目中首先定义了d为一…

性能测试包含哪些内容?

性能测试是对软件产品在特定条件下的性能进行测试和评估的过程。性能测试的内容可以包括以下几个方面&#xff1a; 1、负载测试&#xff1a;负载测试是指在特定条件下&#xff0c;对软件产品的性能进行测试和评估。测试人员可以通过模拟不同的用户数量、并发请求、访问频率等…

el-popover 通过js手动控制弹出框显示、隐藏

el-popover 通过js手动控制弹出框显示、隐藏 说明 element ui 2.x中&#xff0c;el-popover的显示隐藏有4种触发方式&#xff1a;click/focus/hover/manual&#xff0c;分别是点击/聚焦/悬浮/手动&#xff0c;正常情况这几个触发方式已经能满足大部分需求&#xff0c;但有些业…

C++毕业设计基于QT实现的超市收银管理系统源代码+数据库

C毕业设计基于QT实现的超市收银管理系统源代码数据库 编译使用 编译完成后&#xff0c;需要拷贝 file目录下的数据库 POP.db文件到可执行程序目录下 登录界面 主界面 会员管理 完整代码下载地址&#xff1a;基于QT实现的超市收银管理系统源代码数据库

笔记本多拓展出一个屏幕

一、首先要知道&#xff0c;自己的电脑有没有Type-c接口&#xff0c;支持不支持VGA 推荐&#xff1a; 自己不清楚&#xff0c;问客服&#xff0c;勤问。 二、显示屏与笔记本相连&#xff0c;通过VGA 三、连接好了&#xff0c;需要去配置 网址&#xff1a;凑合着看&#xff…

LLM 02-大模型的能力

LLM 02-大模型的能力 我们将深入探讨GPT-3——这个具有代表性的大型语言模型的能力。我们的研究主要基于GPT-3论文中的基准测试&#xff0c;这些测试包括&#xff1a; 标准的自然语言处理&#xff08;NLP&#xff09;基准测试&#xff0c;例如问题回答&#xff1b;一些特殊的一…

【OpenCV • c++】图像噪音 | 椒盐噪音 | 高斯噪音

文章目录 一、什么是图像噪音二、椒盐噪声三、高斯噪声 一、什么是图像噪音 图像噪声是图像在获取或是传输过程中受到随机信号干扰&#xff0c;妨碍人们对图像理解及分析处理的信号。很多时候将图像噪声看做多维随机过程&#xff0c;因而描述噪声的方法完全可以借用随机过程的描…

aruco码DICT几乘几是啥含义,aruco.getPredefinedDictionary

dictionary aruco.getPredefinedDictionary(aruco.DICT_5X5_100) aruco.DICT_5X5_100中的5X5和100表示: - 5X5:表示ArUco标记是5x5像素大小的正方形格子组成。 - 100:表示这个字典包含100个不同的ArUco标记。aruco代码字典中包含多个不同的二进制marker,每个marker由一系列…

PyCharm中使用matplotlib.pyplot.show()报错MatplotlibDeprecationWarning的解决方案

其实这只是一个警告&#xff0c;忽略也可。 一、控制台输出 MatplotlibDeprecationWarning: Support for FigureCanvases without a required_interactive_framework attribute was deprecated in Matplotlib 3.6 and will be removed two minor releases later. MatplotlibD…

AttributeError: module ‘OpenSSL.SSL’ has no attribute ‘SSLv3_METHOD

这个错误是由于在OpenSSL.SSL模块中找不到SSLv3_METHOD属性导致的。解决这个问题的方法如下&#xff1a; 首先&#xff0c;确保你已经安装了最新版本的cryptography和pyOpenSSL。你可以使用以下命令卸载并重新安装它们&#xff1a; 卸载cryptography&#xff1a;pip uninstall …

Java“牵手”微店商品列表页数据采集+微店商品价格数据排序,微店API接口申请指南

微店平台创立于2011年5月&#xff0c;是北京口袋时尚科技开发的应用&#xff0c;2014年1月"微店"APP正式上线。微店已经从小微店主首选的开店工具转型为助力创业者发展兴趣、创立品牌、玩成事业的系统及基础设施。 微店商品列表数据包含商品名称、价格、销量、详情、…

微信小程序 通过 pageScrollTo 滚动到界面指定位置

我们可以先创建一个page 注意 一定要在page中使用 因为pageScrollTo控制的是页面滚动 你在组件里用 他就失效了 我们先来看一个案例 wxml 代码如下 <view><button bindtap"handleTap">回到指定位置</button><view class "ControlHeight…

js 小数相乘后,精度缺失问题,记录四舍五入,向下取整

在做项目的时候&#xff0c;有一个计算金额的&#xff0c;结果发现计算的金额总是缺失0.01&#xff0c;发现相乘的时候&#xff0c;会失去精度&#xff0c;如图所示。被这整的吐血&#xff0c;由于计算逻辑由前端计算&#xff0c;所以传值后端总出错(尽量后端计算)。 还发现to…

9月12日作业

作业代码 #include <iostream>using namespace std;class Shape { protected:double cir;double area; public://无参构造Shape() {cout<<"无参构造"<<endl;}//有参构造Shape(double c, double a):cir(c), area(a){cout<<"有参构造&quo…

IDEFICS 简介: 最先进视觉语言模型的开源复现

我们很高兴发布 IDEFICS ( Image-aware Decoder Enhanced la Flamingo with Ininterleaved Cross-attention S ) 这一开放视觉语言模型。IDEFICS 基于 Flamingo&#xff0c;Flamingo 作为最先进的视觉语言模型&#xff0c;最初由 DeepMind 开发&#xff0c;但目前尚未公开发布…

极简B站直播录制工具 录播姬 2.9.0,支持自动批量录制、弹幕录制等

录播姬 是一个简单好用免费开源的直播录制工具&#xff0c;支持自动批量录制、弹幕录制、实时监控直播间状态&#xff0c;直接获取直播流&#xff0c;非录制屏幕&#xff0c;没有二次压制 软件特点 使用简单&#xff1a;粘贴房间号或房间链接即可开录 自动录制&#xff1a;主…