376.摆动序列

376. 摆动序列

376.摆动序列_第1张图片

这个题既可以用贪心做,也可以用动态规划做。

贪心算法

要使用贪心算法最关键的条件是局部最优能够推出整体最优,即小局部的最优可以推出大局部的最优,局部慢慢变大就成了整体,最后推出整体最优,这里很明显整体和局部的构造是相同的,所以可以用贪心算法,那怎么找局部最优呢,这道题就是给一个局部,然后把其中不符合条件的直接删除即可,我们可以整体序列看作这样的一个图:

376.摆动序列

图片来源:代码随想录

局部最优就是删除那些连续向上或向下的点,所以我们只需要判断当前点是否为连续点还是波峰或波谷,若是后两者,则摆动序列最大长度加1,注意最后一个节点我们没有判断,而最后一个节点总能成为波峰或波谷,所以一开始的长度就为1。代码如下:

class Solution {
public:
    int wiggleMaxLength(vector<int>& nums) {
        if (nums.size() <= 1)
            return nums.size();
        int curdiff;
        int prediff = 0;
        int result = 1;
        for (int i = 0; i < nums.size() - 1; i++) {
            curdiff = nums[i + 1] - nums[i];
            if (prediff >= 0 && curdiff < 0 || prediff <= 0 && curdiff > 0) {
                result++;
                prediff = curdiff;
            }
        }
        return result;
    }
};

动态规划:

动态规划是使用前面的信息求取后面的数据,求后面的数据时往往要比较两种情况的好坏。

这里的动态规划时间复杂度会高一些而且不容易想到。完成一个动态规划相当于填一个表,即dp数组。

首先搞懂dp[i] [j]的含义,dp[i] [0]表示第i个数做波峰时前i个数摆动序列最大长度,dp[i] [1]表示第j个数做波谷时前i个数摆动序列最大长度。

每一个数即可与前面的数组合,又可自己作为一个序列的开端(此时长度为1),所以要比较各种情况的好坏。

即:

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

代码如下:

class Solution {
public:
    int wiggleMaxLength(vector<int>& nums) {
        int dp[1005][2];
        dp[0][0] = 1;
        dp[0][1] = 1;
        for (int i = 1; i < nums.size(); i++) {
            dp[i][0] = 1;
            dp[i][1] = 1;
            for (int j = 0; j < i; j++) {
                if (nums[i] > nums[j]) {
                    dp[i][0] = max(dp[i][0], dp[j][1] + 1);
                }
            }
            for (int j = 0; j < i; j++) {
                if (nums[i] < nums[j]) {
                    dp[i][1] = max(dp[i][1], dp[j][0] + 1);
                }
            }
        }
        return max(dp[nums.size() - 1][0], dp[nums.size() - 1][1]);
    }
};

总结

贪心算法使用的条件是局部最优能推出整体最优,即局部与整体构造相同。使用的方法是从头开始,扩大局部直到整体,每一步都要保证最优。贪心算法最关键的点在于扩大局部时保持最优。

动态规划必须满足最优化原理和无后效性才适用动态规划。

最优化原理(最优子结构性质):一个最优化策略的子策略总是最优的。所以不管过去的过程如何,只从当前的状态和系统的最优化要求出发,作出下一步的最优决策。

无后效性:对于某个给定的阶段状态,它以前各阶段的状态无法直接影响它未来的决策。换句话说,每个状态都是过去历史的一个完整总结。

动态规划最重要的有三点:dp[i] [j]的含义;转移方程;dp初始化

阶段状态,它以前各阶段的状态无法直接影响它未来的决策。换句话说,每个状态都是过去历史的一个完整总结。

动态规划最重要的有三点:dp[i] [j]的含义;转移方程;dp初始化。

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