子数组不同元素数目的平方和 I
同下。
使二进制字符串变美丽的最少修改次数
长度为偶数的字符串要满足条件,那么将数组分为长度为 \(2\) 的各个小段,使各个子数组满足条件一定是最优的。
1 | class Solution { |
和为目标值的最长子序列的长度
0-1 背包,转移方程为 \(dp[i][j]=\max(dp[i-1][j],dp[i-1][j-nums[i]]+1)\),注意初始化为 \(-1\),并在转移时判断有效性。
1 | class Solution { |
子数组不同元素数目的平方和 II
动态规划 + 线段树,刚学的线段树就用上了,但是不太熟练,忘记我的线段树板子是从下标一开始操作,并且没有特判,如果操作的右端点比左端点小,那么就会导致数组越界,之后得修改一下板子。假设以 \(i\) 为右端点的所有子数组的不同计数的平方和为 \(dp[i]\),考虑如何转移到 \(dp[i+1]\)。
如果在 \([0,i]\) 中和 \(nums[i+1]\) 相等的数为 \(nums[j]\),则添加 \(nums[i+1]\) 会使左端点在 \([j+1,i]\) 范围内的子数组的不同计数加 \(1\),而左端点在 \([0,j]\) 范围内子数组的不同计数不变,最后不要忘记加上左端点在 \(i+1\) 的子数组的不同计数的平方。我们可以得到如下转移方程,其中 \(x_{i,j}\) 表示子数组 \(nums[i,j]\) 的不同计数。
然后我们将 \(dp[i]\) 代入到 \(dp[i+1]\) 中,得到:
首先我们需要得到每个数,它左边第一个相同的数的位置,这可以在遍历的过程中使用哈希表得到。然后我们需要维护以当前位置为右端点,所有左端点表示的子数组的不同计数(区间修改),并且需要快速的求区间和,那么就可以使用线段树,这样我们只需要花费 \(O(\log{n})\) 的时间进行转移。转移之后,不要忘记更新左端点在 \([j+1,i+1]\) 范围内的子数组的不同计数。
1 | class Solution { |