本文主要是介绍【算法学习笔记】29:动态规划中可丢弃状态的维度压缩,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
1 动机
当状态 i i i只依赖于前置状态 i − 1 i - 1 i−1,并且在计算出状态 i i i之后就可以丢弃状态 i − 1 i - 1 i−1时的解时, i − 1 i - 1 i−1就成为一个可丢弃的状态,因此就可以将 i i i这个维度直接压缩(省略)掉,用一个变量不停的更新自己就可以了,可以直接节省一个维度的空间占用。
2 例题
2.1 LC1955. 统计特殊子序列的数目
状态表示: f ( i , j ) f(i, j) f(i,j)
- 集合:对于 0.. i 0..i 0..i组成的子数组, j = 0 j = 0 j=0时表示全0, j = 1 j = 1 j=1时表示正整数个0后接正整数个1, j = 2 j = 2 j=2时表示正整数个0后接正整数个1后接正整数个2,如此子序列组成的集合
- 属性:Count(集合中元素的数量)
记 x x x为 n u m s [ i ] nums[i] nums[i],则有状态转移:
- 当 x = 0 x = 0 x=0, f ( i , 0 ) = 2 ∗ f ( i − 1 , 0 ) + 1 f(i, 0) = 2 * f(i - 1, 0) + 1 f(i,0)=2∗f(i−1,0)+1,这个 2 ∗ 2 * 2∗表示 i i i位置的元素选或者不选, + 1 +1 +1表示这个 i i i位置的新的 0 0 0自己组成的新的子序列
- 当 x > 0 x > 0 x>0, f ( i , x ) = 2 ∗ f ( i − 1 , x ) + f ( i − 1 , x − 1 ) f(i, x) = 2 * f(i - 1, x) + f(i - 1, x - 1) f(i,x)=2∗f(i−1,x)+f(i−1,x−1)
- 对于 y ∈ [ 0..2 ] ∣ y ≠ x y \in [0..2]~|~y \neq x y∈[0..2] ∣ y=x, f ( i , y ) = f ( i − 1 , y ) f(i, y) = f(i - 1, y) f(i,y)=f(i−1,y)
初始时, f ( 0 , > 0 ) = 0 f(0, >0) = 0 f(0,>0)=0,如果首个元素是 0 0 0那么 f ( 0 , 0 ) = 1 f(0, 0) = 1 f(0,0)=1,否则 f ( 0 , 0 ) = 0 f(0, 0)= 0 f(0,0)=0
class Solution {
public:int countSpecialSubsequences(vector<int>& nums) {constexpr int mod = 1e9 + 7;int n = nums.size();vector<vector<int>> f(n, vector<int>(3, 0));if (0 == nums[0]) f[0][0] = 1;for (int i = 1; i < n; i ++ ){for (int j = 0; j < 3; j ++ )f[i][j] = f[i - 1][j];if (0 == nums[i])f[i][0] = ((2 * f[i - 1][0]) % mod + 1) % mod;elsef[i][nums[i]] = ((2 * f[i - 1][nums[i]]) % mod + f[i - 1][nums[i] - 1]) % mod;}return f[n - 1][2];}
};
这里用了二维数组来存每个状态,但注意到 i i i只依赖 i − 1 i - 1 i−1进行状态转移,并且返回的也是 n − 1 n - 1 n−1时的结果,所以 i − 1 i - 1 i−1是一个可丢弃状态,因此可以进行空间压缩,直接把 i i i这个维度去掉即可:
class Solution {
public:int countSpecialSubsequences(vector<int>& nums) {constexpr int mod = 1e9 + 7;int n = nums.size();int f[3] = {nums[0] ? 0 : 1, 0, 0};for (int i = 1; i < n; i ++ ){if (0 == nums[i])f[0] = ((2 * f[0]) % mod + 1) % mod;elsef[nums[i]] = ((2 * f[nums[i]]) % mod + f[nums[i] - 1]) % mod;}return f[2];}
};
这篇关于【算法学习笔记】29:动态规划中可丢弃状态的维度压缩的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!