【动态规划刷题 13】最长递增子序列&& 摆动序列

简介: 【动态规划刷题 13】最长递增子序列&& 摆动序列

300. 最长递增子序列

链接: 300. 最长递增子序列

1.状态表示*

dp[i] 表⽰:以 i 位置元素为结尾的「所有⼦序列」中,最⻓递增⼦序列的⻓度。

2.状态转移方程

对于 dp[i] ,我们可以根据「⼦序列的构成⽅式」,进⾏分类讨论:

  1. i. ⼦序列⻓度为 1 :只能⾃⼰玩了,此时 dp[i] = 1 ;ii. ⼦序列⻓度⼤于 1 : nums[i] 可以跟在前⾯任何⼀个数后⾯形成⼦序列。 设前⾯的某⼀个数的下标为 j ,其中 0 <= j <= i - 1 。

只要 nums[j] < nums[i] , i 位置元素跟在 j 元素后⾯就可以形成递增序列,⻓度

为 dp[j] + 1 。

因此,我们仅需找到满⾜要求的最⼤的 dp[j] + 1 即可。

综上, dp[i] = max(dp[j] + 1, dp[i]) ,其中 0 <= j <= i - 1 && nums[j]< nums[i]

3. 初始化

所有的元素「单独」都能构成⼀个递增⼦序列,因此可以将 dp 表内所有元素初始化为 1 。

4. 填表顺序

显⽽易⻅,填表顺序「从左往右」

5. 返回值

由于不知道最⻓递增⼦序列以谁结尾,因此返回 dp 表⾥⾯的「最⼤值」。

代码:

 int lengthOfLIS(vector<int>& nums) {
      int n=nums.size();
        vector<int> dp(n,1);
        int Max=1;
        for(int i=1;i<n;i++)
        {
            for(int j=0;j<i;j++)
            {
                if(nums[i]>nums[j])
                dp[i]=max(dp[j]+1,dp[i]);
            }
            Max=max(Max,dp[i]);
        }
        return Max;
    }

376. 摆动序列

链接: 376. 摆动序列

如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为 摆动序列 。第一个差(如果存在的话)可能是正数或负数。仅有一个元素或者含两个不等元素的序列也视作摆动序列。


例如, [1, 7, 4, 9, 2, 5] 是一个 摆动序列 ,因为差值 (6, -3, 5, -7, 3) 是正负交替出现的。


相反,[1, 4, 7, 2, 5] 和 [1, 7, 4, 5, 5] 不是摆动序列,第一个序列是因为它的前两个差值都是正数,第二个序列是因为它的最后一个差值为零。

子序列 可以通过从原始序列中删除一些(也可以不删除)元素来获得,剩下的元素保持其原始顺序。


给你一个整数数组 nums ,返回 nums 中作为 摆动序列 的 最长子序列的长度 。


示例 1:


输入:nums = [1,7,4,9,2,5]

输出:6

解释:整个序列均为摆动序列,各元素之间的差值为 (6, -3, 5, -7, 3) 。

示例 2:


输入:nums = [1,17,5,10,13,15,10,5,16,8]

输出:7

解释:这个序列包含几个长度为 7 摆动序列。

其中一个是 [1, 17, 10, 13, 10, 16, 8] ,各元素之间的差值为 (16, -7, 3, -3, 6, -8) 。

示例 3:


输入:nums = [1,2,3,4,5,6,7,8,9]

输出:2


1.状态表示*

  1. f[i] 表⽰:以 i 位置元素为结尾的所有的⼦序列中,最后⼀个位置呈现「上升趋势」的最⻓摆动序列的⻓度;
  2. g[i] 表⽰:以 i 位置元素为结尾的所有的⼦序列中,最后⼀个位置呈现「下降趋势」的最⻓摆动序列的⻓度。

2.状态转移方程

由于⼦序列的构成⽐较特殊, i 位置为结尾的⼦序列,前⼀个位置可以是 [0, i - 1] 的任意位置,因此设 j 为 [0, i - 1] 区间内的某⼀个位置。

对于 f[i] ,我们可以根据「⼦序列的构成⽅式」,进⾏分类讨论:

  1. i. ⼦序列⻓度为 1 :只能⾃⼰玩了,此时 f[i] = 1
  2. ii. ⼦序列⻓度⼤于 1 :因为结尾要呈现上升趋势,因此需 nums[j] < nums[i] 在满 ⾜这个条件下, j 结尾需要呈现下降状态,最⻓的摆动序列就是 g[j] + 1
    因此我们要找出所有满⾜条件下的最⼤的 g[j] + 1 。

综上, f[i] = max(g[j] + 1, f[i]) ,注意使⽤ g[j] 时需要判断。

g[i]则类似。

3. 初始化

所有的元素「单独」都能构成⼀个摆动序列,因此可以将 dp 表内所有元素初始化为 1 。

4. 填表顺序

显⽽易⻅,填表顺序「从左往右」

5. 返回值

应该返回「两个 dp 表⾥⾯的最⼤值」,我们可以在填表的时候,顺便更新⼀个「最⼤值」

代码:

 int n=nums.size();
        vector<int> f(n,1),g(n,1);
        int Max=1;
        for(int i=1;i<n;i++)
        {
            for(int j=0;j<i;j++)
            {
                if(nums[i]>nums[j])
                {
                    f[i]=max(f[i],g[j]+1);
                }
                if(nums[i]<nums[j])
                {
                    g[i]=max(f[j]+1,g[i]);
                }
                Max=max(Max,max(g[i],f[i]));
            }
        }
        return Max;

相关文章
|
算法 测试技术
【学会动态规划】最长湍流子数组(23)
【学会动态规划】最长湍流子数组(23)
41 0
【动态规划刷题 15】最长定差子序列&& 最长的斐波那契子序列的长度
【动态规划刷题 15】最长定差子序列&& 最长的斐波那契子序列的长度
|
人工智能
【动态规划刷题 11】等差数列划分&& 最长湍流子数组
【动态规划刷题 11】等差数列划分&& 最长湍流子数组
|
1月前
|
算法
动态规划算法学习二:最长公共子序列
这篇文章介绍了如何使用动态规划算法解决最长公共子序列(LCS)问题,包括问题描述、最优子结构性质、状态表示、状态递归方程、计算最优值的方法,以及具体的代码实现。
116 0
动态规划算法学习二:最长公共子序列
|
6月前
|
算法
【面试算法——动态规划 20】最长公共子序列&& 不相交的线
【面试算法——动态规划 20】最长公共子序列&& 不相交的线
|
6月前
代码随想录Day45 动态规划13 LeetCode T1143最长公共子序列 T1135 不相交的线 T53最大子数组和
代码随想录Day45 动态规划13 LeetCode T1143最长公共子序列 T1135 不相交的线 T53最大子数组和
58 0
|
6月前
|
算法 程序员
【算法训练-动态规划 二】【线性DP问题】连续子数组的最大和、乘积最大子数组、最长递增子序列
【算法训练-动态规划 二】【线性DP问题】连续子数组的最大和、乘积最大子数组、最长递增子序列
104 0
|
算法 C语言 C++
【动态规划】最长上升子序列(单调队列、贪心优化)
本篇是对最长上升子序列基础做法的一种优化
66 0
深入理解动态规划算法 - 最长公共子序列
深入理解动态规划算法 - 最长公共子序列
75 0
|
算法
LeetCode:376. 摆动序列——说什么贪心和动规~
如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为 摆动序列 。第一个差(如果存在的话)可能是正数或负数。仅有一个元素或者含两个不等元素的序列也视作摆动序列。 例如, [1, 7, 4, 9, 2, 5] 是一个 摆动序列 ,因为差值 (6, -3, 5, -7, 3) 是正负交替出现的。 相反,[1, 4, 7, 2, 5] 和 [1, 7, 4, 5, 5] 不是摆动序列,第一个序列是因为它的前两个差值都是正数,第二个序列是因为它的最后一个差值为零。 子序列 可以通过从原始序列中删除一些(也可以不删除)元素来获得,剩下的元素保持其原始顺序。
112 0