LeetCode·376.摆动序列·贪心·动态规划

链接:https://leetcode.cn/problems/wiggle-subsequence/solution/-by-xun-ge-v-nh8y/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 

题目LeetCode·376.摆动序列·贪心·动态规划_第1张图片

 

示例LeetCode·376.摆动序列·贪心·动态规划_第2张图片

 

思路

解题思路
【贪心】

贪心思维在于局部最优推出全局最优

对于每一个序列我们都取最大数目时(局部最优),最后的序列一定的最大的(全局最优)

具体实现看代码,注释超级详细

【动态规划】
很容易可以发现,对于我们当前考虑的这个数,要么是作为山峰(即nums[i] > nums[i-1]),要么是作为山谷(即nums[i] < nums[i - 1])。

  • 设dp状态dp[i][0],表示考虑前i个数,第i个数作为山峰的摆动子序列的最长长度
  • 设dp状态dp[i][1],表示考虑前i个数,第i个数作为山谷的摆动子序列的最长长度

则转移方程为:

  • dp[i][0] = max(dp[i][0], dp[j][1] + 1),其中0 < j < i且nums[j] < nums[i],表示将nums[i]接到前面某个山谷后面,作为山峰。
  • dp[i][1] = max(dp[i][1], dp[j][0] + 1),其中0 < j < i且nums[j] > nums[i],表示将nums[i]接到前面某个山峰后面,作为山谷。

初始状态:

由于一个数可以接到前面的某个数后面,也可以以自身为子序列的起点,所以初始状态为:
dp[i][0] = dp[i][1] = 1。

代码

【贪心】

int wiggleMaxLength(int* nums, int numsSize){
    int curDiff = 0; // 当前一对差值
    int preDiff = 0; // 前一对差值
    int result = 1;  // 记录峰值个数,序列默认序列最右边有一个峰值
    for (int i = 0; i < numsSize - 1; i++) {
        curDiff = nums[i + 1] - nums[i];
        // 出现峰值
        if ((curDiff > 0 && preDiff <= 0) || (preDiff >= 0 && curDiff < 0)) {
            result++;
            preDiff = curDiff;
        }
    }
    return result;
}

作者:xun-ge-v
链接:https://leetcode.cn/problems/wiggle-subsequence/solution/-by-xun-ge-v-nh8y/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

【动态规划】

int wiggleMaxLength(int* nums, int numsSize){
    int dp[numsSize][2];//定义dp数组
    for (int i = 0; i < numsSize; ++i)//枚举数组元素
    {
        dp[i][0] = dp[i][1] = 1;

        for (int j = 0; j < i; ++j)//更新dp数组
        {
            if (nums[j] > nums[i]) dp[i][1] = fmax(dp[i][1], dp[j][0] + 1);
            if (nums[j] < nums[i]) dp[i][0] = fmax(dp[i][0], dp[j][1] + 1);
        }
    }
    return fmax(dp[numsSize - 1][0], dp[numsSize - 1][1]);
}

作者:xun-ge-v
链接:https://leetcode.cn/problems/wiggle-subsequence/solution/-by-xun-ge-v-nh8y/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

你可能感兴趣的:(LeetCode刷题笔记,leetcode,算法,贪心算法)