leetcode_376. Wiggle Subsequence(DP 和 Greedy)
来源:互联网 发布:数组.length 编辑:程序博客网 时间:2024/06/18 15:19
A sequence of numbers is called a wiggle sequence if the differences between successive numbers strictly alternate between positive and negative. The first difference (if one exists) may be either positive or negative. A sequence with fewer than two elements is trivially a wiggle sequence.
For example, [1,7,4,9,2,5] is a wiggle sequence because the differences (6,-3,5,-7,3) are alternately positive and negative. In contrast, [1,4,7,2,5] and [1,7,4,5,5] are not wiggle sequences, the first because its first two differences are positive and the second because its last difference is zero.
Given a sequence of integers, return the length of the longest subsequence that is a wiggle sequence. A subsequence is obtained by deleting some number of elements (eventually, also zero) from the original sequence, leaving the remaining elements in their original order.
Examples:
Input: [1,7,4,9,2,5]
Output: 6
The entire sequence is a wiggle sequence.
Input: [1,17,5,10,13,15,10,5,16,8]
Output: 7
There are several subsequences that achieve this length. One is [1,17,10,13,10,16,8].
Input: [1,2,3,4,5,6,7,8,9]
Output: 2
DP
题意:
给定一个序列,找出其中最长的子序列,使得该子序列相邻两个数的差值(后一个减去前一个)形成的序列正负交替(不能为0)。
分析:
- 该题可以用动态规划(DP)解决,我们作如下考虑:假设以i为最后一个元素的子序列中,wiggle sequence的最后一个值为负数的最优解为dec[i],最后一个值为整数的最优解为inc[i],则最优解max[i] = max{inc[i], dec[i]}。
- 下面分析最优子结构性质,对于dec[i],该子序列的前一个元素为j(j< i & nums[i] < nums[j]),则inc[j] = dec[i] - 1,若不然,设存在以j为最后一个元素且wiggle sequence中最后一个数为正数的子序列S个数为m, m > dec[i] - 1,则序列S + nums[i] 满足wiggle sequence,即存在以i为最后一个元素且wiggle sequence中最后一个数为负数的子序列S + nums[i],个数为 m + 1 > inc[j] + 1 = dec[i],这以假设dec[i]为以i为最后一个元素且wiggle sequence中最后一个数为负数的最优解矛盾。inc[i]的证明类似。
递推公式:
代码(c++, O(
class Solution {public: int wiggleMaxLength(vector<int>& nums) { vector<int> inc(nums.size(), 1); vector<int> dec(nums.size(), 1); int maxs = (nums.size() == 0 ? 0 : 1); for(int i = 1; i < nums.size(); i++){ for(int j = 0; j < i; j++){ if(nums[i] > nums[j] && dec[j] + 1 > inc[i]) inc[i] = dec[j] + 1; if(nums[i] < nums[j] && inc[j] + 1 > dec[i]) dec[i] = inc[j] + 1; } maxs = max(maxs, max(inc[i], dec[i])); } return maxs; }};
Greedy
后来看了一下题目最后有一句话:Can you do it in O(n) time? 上面的DP虽然可以过,但是时间复杂度为O(
分析:
我们可以这样分析:假设合法的子序列中第一个数为正数(> 0),设该序列为
证明:
- 假如部分子序列
[x1,x2,x3,x4,...,xm] 中,nums[x_m] > nums[x_{m-1}],那么接下来添加的数必须满足nums[x_i] < nums[x_m],如果不满足,则用i替换xm ,替换后的序列为[x1,x2,x3,x4,...,xm−1,i] ,因为nums[i] > nums[xm ],所以nums[i] > nums[xm−1 ],替换后的序列合法, - 下面证明如果最优序列S中含有
[x1,x2,x3,x4,...,xm] ,一定也存在一个最优序列S’,包含[x1,x2,x3,x4,...,xm−1,i] ,假设 j为S中第一个下标比xm 大的数的下标,S =[x1,x2,x3,x4,...,xm,j] ⋃ S1 ,用i替换xm,因为nums[j]<nums[ x_m]<nums[i],所以S′= [x_1,x_2,x_3,x_4,…,x_m,i]⋃ S1 合法,且|S’| = |S|,所以S’也是最优解。
代码(O(
class Solution {public: int wiggleMaxLength(vector<int>& nums) { int firstinc, firstdec; if(nums.size() == 0) return 0; firstinc = firstdec = 1; int ai, bi; ai = 1, bi = -1; //初始化,ai交替取1和-1,ai*(nums[i] - nums[inc])用于判断差值是否正负交替 for(int i = 1; i < nums.size(); i++){ if(ai * (nums[i] - nums[i-1]) > 0){//合法 ai = -ai; //换方向 firstinc++; } if(bi * (nums[i] - nums[i-1]) > 0){//合法 bi = -bi; firstdec++; } } return max(firstinc, firstdec); }};
- leetcode_376. Wiggle Subsequence(DP 和 Greedy)
- leetcode:greedy:Wiggle Subsequence(376)
- 376. Wiggle Subsequence dp+贪心
- Wiggle Subsequence
- Wiggle Subsequence
- Wiggle Subsequence
- Wiggle Subsequence
- Wiggle Subsequence
- Wiggle Subsequence
- Wiggle Subsequence
- Wiggle Subsequence
- Wiggle Subsequence
- 392. Is Subsequence (greedy)
- 376. Wiggle Subsequence(第十三周)
- 贪心1 Wiggle Subsequence(LeetCode376)
- 376. Wiggle Subsequence(摆动子序列)
- DP (10) -- Wiggle Subsequence,Search a 2D Matrix II
- leetcode 376. Wiggle Subsequence 最长摆动序列 + 动态规划DP
- Linux声音系统
- 实战:mysql版本升级
- ArrayList,Vector, LinkedList的存储性能和特性
- centos6.5下载地址
- Hadoop:hadoop的起缘和发展史
- leetcode_376. Wiggle Subsequence(DP 和 Greedy)
- OC_模糊搜索
- 直接拿来用,最火的Android开源项目
- 指针的定义和使用
- java连接JDBC
- groovy语法基础
- NEFUOJ 564 汉诺塔
- Codeforces 689D Friends and Subsequences
- 详解Android中AsyncTask的使用