子序列和子数组 - wenzhoullq/leetcode GitHub Wiki

字母串

子序列

dp设计为前i个的26个字母表,状态的转移为选和不选

一般子序列是O(n+m),一个for循环双指针比较

方案数

940. 不同的子序列 II

最值

子序列

子序列最值的重点在于非连续,因此可以重排,重排后用贡献法

最少修改满足不严格递增本质就是找最长上升子序列,n - 最长上升子序列;

严格单调递增,满足如下性质: i > j ,那么 a[i] - a[j] >= i - j, 即 a[i] - i > = a[j] - i, b[i] = a[i] - i,即找b[i] 的不严格单调最长上升子序列

891. 子序列宽度之和

子数组

子数组是连续的

如果是求子数组的最值,那么都是用单调栈

这里有个值得注意的点,如果是求最小值,那么维护的是单调递增栈,如果是求最大值,则将nums[i]*-1,还是用单调递增栈

子数组还有个应用是滑动窗口,滑动窗口的本质跟单调性有点像,只要你left不断向i靠近,那么就会越会向不满足的方向靠拢

        int len = nums.length,ans = 0 ,INF = Integer.MIN_VALUE;
        Stack<Integer> s = new Stack<>();
        s.push(INF);
        for(int i = 0 ; i <= len ;i++){
            int cur = i==len?INF:nums[i];//如果是最大值,则是INF:-nums[i]
            while(s.size()>1&&nums[s.peek()]>cur){//如果是最大值,-nums[i]>cur
                int index = s.pop();
                ans+=(i-index)*(index-(s.peek()==INF?-1:s.peek()));//贡献法,求个数
                ans= Math.max(ans,);//求最值
            }
            s.push(i);
        }
        return ans;

题目

  • 贡献法
贡献的个数计算
int index = st.pop()
(index - s.peek()) * (i - index + 1)

907. 子数组的最小值之和

2818. 操作使得分最大

  • 滑动窗口

2398. 预算内的最多机器人数目

2537. 统计好子数组的数目

  • 求最值

42. 接雨水维持最小值,但是因为是淹没的,因此在处理上有些许不同

84. 柱状图中最大的矩形

85. 最大矩形

1793. 好子数组的最大分数

2334. 元素值大于变化阈值的子数组

B. Mike and Feet-灵茶-1.11 也是同一个模板,主要的思考点在于长度为2的子数组的最大值和长度为1的子数组的最大值之间的关系

  • 字母DP

1759. 统计同构子字符串的数目

数组集合单调值

第一个不满足集合条件的是最左边界,满足了集合条件的不断求他的最大值

795. 区间子数组个数

2444. 统计定界子数组的数目

分割成k个的方案数

分割方案有个很重要的点是初始化问题,因为连续的,第k个合法的前提是第k-1合法,如果想不明白的话。 如果是求最大值dp初始化为最小值,求最小值dp初始化为最大值,最后把有意义的dp[0][0]=0; 如果是求方案书的话,dp[0][0]=1即可 DP

题目

813. 最大平均值和的分组

6244. 完美分割的方案数

字符串的匹配

枚举末端的差值 d = 1 -m ~ n , 枚举起点; 需要注意的是起点的

1638. 统计只差一个字符的子串数目

⚠️ **GitHub.com Fallback** ⚠️