zoukankan      html  css  js  c++  java
  • 0376. Wiggle Subsequence (M)

    Wiggle Subsequence (M)

    题目

    Given an integer array nums, return the length of the longest wiggle sequence.

    A wiggle sequence is a sequence where 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.

    A subsequence is obtained by deleting some elements (eventually, also zero) from the original sequence, leaving the remaining elements in their original order.

    Example 1:

    Input: nums = [1,7,4,9,2,5]
    Output: 6
    Explanation: The entire sequence is a wiggle sequence.
    

    Example 2:

    Input: nums = [1,17,5,10,13,15,10,5,16,8]
    Output: 7
    Explanation: There are several subsequences that achieve this length. One is [1,17,10,13,10,16,8].
    

    Example 3:

    Input: nums = [1,2,3,4,5,6,7,8,9]
    Output: 2
    

    Constraints:

    • 1 <= nums.length <= 1000
    • 0 <= nums[i] <= 1000

    Follow up: Could you solve this in O(n) time?


    题意

    在数组中找到一个子序列,使得子序列中每两个元素的差值一正一负。

    思路

    比较容易想到的是动态规划。dp[i]表示以nums[i]为结尾的满足条件的子序列的长度,且若最后两个元素之间的差值为负数,dp[i]为负数。对于每一个i,遍历j从0 ~ i-1,找到nums[i]能与dp[j]组成的最大长度的子序列。时间复杂度为(O(N^2))

    (O(N))动态规划:维护两个数组up和down,up[i]表示子数组nums[0-i]中能找到的符合条件的子序列的最大长度,且该子序列的最后一个元素大于倒数第二个元素;down[i]表示子数组nums[0-i]中能找到的符合条件的子序列的最大长度,且该子序列的最后一个元素小于倒数第二个元素。遍历数组,如果当前元素大于前一个,说明可以拓展down[i-1]代表的子序列来得到up[i];如果当前元素小于前一个,说明可以拓展up[i-1]代表的子序列来得到down[i]。为了进一步减小空间复杂度,可以直接用up和down两个整数来代替数组。


    代码实现

    Java

    动态规划 O(N^2)

    class Solution {
        public int wiggleMaxLength(int[] nums) {
            if (nums.length < 2) return nums.length;
    
            int maxLen = 1;
            int[] dp = new int[nums.length];
    
            for (int i = 1; i < nums.length; i++) {
                for (int j = 0; j < i; j++) {
                    int diff = nums[i] - nums[j];
                    if (diff * dp[j] < 0 && Math.abs(dp[j]) + 1 > Math.abs(dp[i])) {
                        dp[i] = dp[j] < 0 ? -dp[j] + 1 : -dp[j] - 1;
                    } else if (dp[j] == 0 && diff != 0 && Math.abs(dp[i]) < 2) {
                        dp[i] = diff < 0 ? -2 : 2;
                    }
                }
                maxLen = Math.max(maxLen, Math.abs(dp[i]));
            }
    
            return maxLen;
        }
    }
    

    动态规划 O(N)

    class Solution {
        public int wiggleMaxLength(int[] nums) {
            if (nums.length < 2) return nums.length;
    
            int up = 1, down = 1;
    
            for (int i = 1; i < nums.length; i++) {
                if (nums[i] > nums[i - 1]) {
                    up = down + 1;
                } else if (nums[i] < nums[i - 1]) {
                    down = up + 1;
                }
            }
    
            return Math.max(up, down);
        }
    }
    
  • 相关阅读:
    OpenCV笔记——cvFloodFill漫水填充算法
    C# 总结 随笔
    MYSQL存储过程 随笔
    MYSQL总结 随笔
    xPath 总结 随笔
    Javascript 总结 随笔
    linux中top查看cpu使用率超过100%
    页面优化小记1
    基于数据库的多语言解决方案
    基于消息队列的日志组件
  • 原文地址:https://www.cnblogs.com/mapoos/p/14555345.html
Copyright © 2011-2022 走看看