代码随想录总结(一) 贪心

376. 摆动序列

1. 贪心方法

我主要纠结
a. 递增序列一定是要删除的,但是如何才能做到删除得最少呢?
b. 递增连着递减,删除顶峰值会不会出现两个峰?
c. 删除单调区间内的点,尽可能少。没有确定要“删除单调坡度上的节点”。整体最优也没想到。

编程上需要避免的

  1. 能基于数,就不基于间距。一开始我想弄一个数组去描述某个元素之后的升降,但总是少一个。
  2. 能从0开始绝对不从1开始。如函数 wiggleMaxLength_OK
贪心
int wiggleMaxLength_OK(vector<int>& nums) {
    
    int before = 0;  
    int result = 1;
    for (int i = 0; i < nums.size() - 1; i++) // for (int i = 1; i < nums.size() - 1; i++) 会少最后一个的
    {
        int after = nums[1 + i] - nums[i];
        if ((before <= 0 && after > 0) || (before >= 0 && after < 0))
        {
            result++;
            before = after;
        }
      
    }
    return result;
}

动态规划

复杂的题目首先要明白前提才能进行递推公式:

  1. 什么情况下会产生凸起
    a. (before <= 0 && after > 0) || (before >= 0 && after < 0) 会,我们将这个条件称为凸起条件。(before*after)会漏掉一些情况
    b. 这个 before 是指从上个凸起到目前数的趋势,不是上上个数减去上个数。所以只有当当前数满足凸起条件的时候才更新 before
  2. 明确总问题:长度为i时候凸起的数量

递推公式:
宗问题:
[? ? ? … ? ]i = f(i) ----- 长度为i时候凸起的数量。
子问题:
[? ? ? …?]i-1 ? = f(i-1) ------- 长度为i-1时候凸起的数量。

其中最后一个?可以分为两种完备的情况:情况1:表示第i个可能会造成新的凸起;情况2:也可能不会造成新的凸起。

由此可以推出条件递推公式(这种是没有通项公式的):
如果i满足凸起条件,则 f(i) = f(i-1)+1; 如果不满足条件,则 f(i) = f(i-1)。

递推,dp
int wiggleMaxLength_dp(vector<int>& nums) {

    vector<int>dp(nums.size());
    dp[0] = 1;
    int before = 0;
    for (int i = 1; i < nums.size(); i++)
    {
        int current = nums[i] - nums[i - 1];
        if ((before <= 0 && current > 0) || (before >= 0 && current < 0))
        {
            dp[i] = dp[i - 1] + 1;
            before = current;
        }
        else
        {
            dp[i] = dp[i - 1];
        }
    }
    return dp[dp.size() - 1];
}

逻辑简答的题目主要注意

  1. 子问题以及子子问题的建立
  2. 子问题一定在任何情况下都能用到子子问题

本问题的子问题有两个
a. f(i) 表示数组长度为i的时候,该数组的连续子数组和为f(i);返回dp[last] 就好
b. 表示以第 i 个数结尾的「连续子数组的最大和」为f(i);返回的是max{dp[i]}
(好像有个技巧:如果像爬楼梯、斐波那契那种最后的值一定是有影响的话,就返回dp[n],这时应该只能假设是a;但本题后面的完全可能是废话,所以可以假设b。实在做不出来的时候,先看看b,然后看看a)

a在这题是不行的 如果你用a,就发现有两种情况:i加入;i不加入。当i加入的时候,无法很好的利用dp[i-1]的值。这就变成暴力了。
还有个想法:从可以推导的地方入手
把题目一般化:[xxxx…xyy…yyx…x]_ x表示不选的,y表示选的,_表示第i个,这个时候你怎么判断 第i个呢? 这就相当于A,给自己找麻烦。注意动态规划是可以从前往后推导出来的,你看看上面哪个值容易计算?肯定是[xxxx…xyy…yy*x *…x] 那个标星号的,也就是求[xxxx…xyy…yy]?的这个问号。如何求呢?

双向贪心

今天学习了一道需要顾及后面的数的贪心题目 135. 分发糖果。
大致解法:

  1. 多维度贪心:先从前到后,再从后到前面。
  2. 递增递减序列;

解法1主要是因为,这个题第i个和前面的和后面的都有关系,而第一遍遍历只能和前面有关系,后面的还没定;第二遍就是把后面的确定下来,然后看前面的。即:i的确定需要依据确定的值,所以只能是第二遍了。

解法2这个比较直观,他发现:下降区间的重要性。

双向贪心2

  1. 根据身高重建队列

你可能感兴趣的:(找工作-算法学习,算法,动态规划)