376 Wiggle Subsequence 贪心解法以及证明

376. Wiggle Subsequence

题目理解

给定一个数组,相邻两个数计算差值。差值排成的序列是正负相间的,那这个数组就是一个wiggle 数组。例如数组[1,7,4,9,2,5],差值序列是(6,-3,5,-7,3)。原数组用坐标轴表示如下。
这里写图片描述

这里写图片描述
思路是:在一段连续上升或者连续下降的线段上,那只保留两端的断点(这是贪心思想的体现),去掉中间的断点,就能使得子序列符合要求。例如在AB线段上,去掉中间点 A1,A2 A 1 , A 2 ,在BC线段上去掉 B1,B2 B 1 , B 2 ,那留下在子序列[A,B,C]就是符合要求的,并且是长度最长的wiggle子序列。
证明:要证明上面的思路是正确的。可以使用反证法。假如在一段连续上升的线段中不是保留最顶点B,而是留下 A2 A 2 点,删除一个点,添加一个点,总长度不发生变化。那会影响其他点吗? A2<B A 2 < B 。B点之后是一段下降的线段。 <A2 < A 2 <script type="math/tex" id="MathJax-Element-879"> <B < B <script type="math/tex" id="MathJax-Element-880"> <B < B <script type="math/tex" id="MathJax-Element-881"> <A2 < A 2 <script type="math/tex" id="MathJax-Element-882"> A2 A 2 替换B没有任何好处。可以用同理分析下降线段中去掉中间点是最合理的。
学习:对于每一种解决方法是应该有证明的。此外,本题目还要考虑各种变化趋势,增加测试数据。
考虑:先直线再折线;先折线再直线;折线折线直线;折线直线折线。

public int wiggleMaxLength(int[] nums) {
        if(nums.length<=1){
            return nums.length;
        }
        int ans = 1;
        int diff = nums[1]-nums[0];
        if(diff!=0){
            ans++;
        }
        for(int i=2;i<nums.length;i++){
            if(nums[i]!=nums[i-1]){
                 if(diff * (nums[i]-nums[i-1])<=0){
                    ans++;
                }
                diff = nums[i]-nums[i-1];
            }
        }
        return ans;
    }
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值