376. 摆动序列(Python)

题目

难度:★★★☆☆
类型:数组
方法:动态规划,贪心算法

传送门

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

例如, [1,7,4,9,2,5] 是一个摆动序列,因为差值 (6,-3,5,-7,3) 是正负交替出现的。相反, [1,4,7,2,5] 和 [1,7,4,5,5] 不是摆动序列,第一个序列是因为它的前两个差值都是正数,第二个序列是因为它的最后一个差值为零。

给定一个整数序列,返回作为摆动序列的最长子序列的长度。 通过从原始序列中删除一些(也可以不删除)元素来获得子序列,剩下的元素保持其原始顺序。

示例

示例 1:

输入: [1,7,4,9,2,5]
输出: 6
解释: 整个序列均为摆动序列。

示例 2:

输入: [1,17,5,10,13,15,10,5,16,8]
输出: 7
解释: 这个序列包含几个长度为 7 摆动序列,其中一个可为[1,17,10,13,10,16,8]。

示例 3:

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

进阶:
你能否用 O(n) 时间复杂度完成此题?

解答

方法1:动态规划

数组问题常常用空间代替时间的动态规划来做,针对此问题,动态规划的一般步骤:

数组定义。这里定义两个数组end_with_up和end_with_down,维度与输入数组是一致的,end_with_up[i](0<=i<len(nums))表示以nums[0:i]子数组中的最长的摆动数组的长度,且该摆动数组倒数第一个元素nums[i]大于倒数第二个元素。end_with_up[i](0<=i<len(nums))表示以nums[0:i]子数组中的最长的摆动数组的长度,且该摆动数组倒数第一个元素nums[i]小于倒数第二个元素。

数组初始化:两个数组中所有元素都初始化为1,因为摆动序列最小长度也是1。

状态转移方程。我们刚刚定义的两个数组是要在迭代过程中互相用到的。具体的用法是:

两次遍历,从1到len(nums)-1遍历数组,确定了子数组的寻找范围[1,i],也就是从0到i的下标位置,这一层遍历,是为了填写end_with_up[i]和end_with_down[j]的,设置下标j(1<=i<len(nums)),确定了第二层遍历的元素nums[j];第二层遍历就是在子数组中寻找可以使得end_with_up[i]和end_with_down[i]最大的组合方式,设置下标j(0<=j<i),确定了第二层遍历的元素nums[j]。

当nums[i]与nums[j]不相等的时候,就可以更新两个数组中的其中一个,具体方式是:
如果nums[j]<nums[i],那么一定可以组成以这两个数结尾的摆动数组,由于最后两个数是上升的,所以需要更新的是end_with_up,考虑到当前该位置可能已经有值,取end_with_up[i] = max(end_with_up[i], end_with_down[j]+1),这里的+1实际上的含义就是在摆动数组末尾增加了数字nums[i];

同样的,如果nums[j]>nums[i],那么一定可以组成以这两个数结尾的摆动数组,由于最后两个数是上升的,所以需要更新的是end_with_down,考虑到当前该位置可能已经有值,取end_with_down[i] = max(end_with_down[i], end_with_up[j]+1),这里的+1实际上的含义就是在摆动数组末尾增加了数字nums[i]。

特殊情况:输入为空数组,直接返回零。

class Solution:
    def wiggleMaxLength(self, nums):
        if not nums:
            return 0

        end_with_up = [1 for _ in range(len(nums))]
        end_with_down = [1 for _ in range(len(nums))]

        for i in range(1, len(nums)):
            for j in range(i):
                if nums[j] < nums[i]:
                    end_with_up[i] = max(end_with_up[i], end_with_down[j]+1)
                elif nums[j] > nums[i]:
                    end_with_down[i] = max(end_with_down[i], end_with_up[j]+1)
        return max(end_with_up+end_with_down)

方法2:贪心

道理其实与以上类似,只是把两个动态规划用的数组换成了两个变量p和q,而且遍历过程也做了简化,时间复杂度和空间复杂度都加倍简化。

class Solution:
    def wiggleMaxLength(self, nums):
        if not nums:
            return 0
        p = q = 1
        for i in range(1, len(nums)):
            if nums[i] > nums[i-1]:
                p = q + 1
            elif nums[i] < nums[i-1]:
                q = p + 1
        return max(p, q)

如有疑问或建议,欢迎评论区留言~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,529评论 5 475
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,015评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,409评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,385评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,387评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,466评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,880评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,528评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,727评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,528评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,602评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,302评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,873评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,890评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,132评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,777评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,310评论 2 342