【算法学习笔记】29:动态规划中可丢弃状态的维度压缩

2024-08-26 02:20

本文主要是介绍【算法学习笔记】29:动态规划中可丢弃状态的维度压缩,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1 动机

当状态 i i i只依赖于前置状态 i − 1 i - 1 i1,并且在计算出状态 i i i之后就可以丢弃状态 i − 1 i - 1 i1时的解时, i − 1 i - 1 i1就成为一个可丢弃的状态,因此就可以将 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)=2f(i1,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)=2f(i1,x)+f(i1,x1)
  • 对于 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(i1,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 i1进行状态转移,并且返回的也是 n − 1 n - 1 n1时的结果,所以 i − 1 i - 1 i1是一个可丢弃状态,因此可以进行空间压缩,直接把 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:动态规划中可丢弃状态的维度压缩的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1107274

相关文章

Flutter监听当前页面可见与隐藏状态的代码详解

《Flutter监听当前页面可见与隐藏状态的代码详解》文章介绍了如何在Flutter中使用路由观察者来监听应用进入前台或后台状态以及页面的显示和隐藏,并通过代码示例讲解的非常详细,需要的朋友可以参考下... flutter 可以监听 app 进入前台还是后台状态,也可以监听当http://www.cppcn

Vue中动态权限到按钮的完整实现方案详解

《Vue中动态权限到按钮的完整实现方案详解》这篇文章主要为大家详细介绍了Vue如何在现有方案的基础上加入对路由的增、删、改、查权限控制,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、数据库设计扩展1.1 修改路由表(routes)1.2 修改角色与路由权限表(role_routes)二、后端接口设计

前端 CSS 动态设置样式::class、:style 等技巧(推荐)

《前端CSS动态设置样式::class、:style等技巧(推荐)》:本文主要介绍了Vue.js中动态绑定类名和内联样式的两种方法:对象语法和数组语法,通过对象语法,可以根据条件动态切换类名或样式;通过数组语法,可以同时绑定多个类名或样式,此外,还可以结合计算属性来生成复杂的类名或样式对象,详细内容请阅读本文,希望能对你有所帮助...

golang字符串匹配算法解读

《golang字符串匹配算法解读》文章介绍了字符串匹配算法的原理,特别是Knuth-Morris-Pratt(KMP)算法,该算法通过构建模式串的前缀表来减少匹配时的不必要的字符比较,从而提高效率,在... 目录简介KMP实现代码总结简介字符串匹配算法主要用于在一个较长的文本串中查找一个较短的字符串(称为

Nginx实现动态封禁IP的步骤指南

《Nginx实现动态封禁IP的步骤指南》在日常的生产环境中,网站可能会遭遇恶意请求、DDoS攻击或其他有害的访问行为,为了应对这些情况,动态封禁IP是一项十分重要的安全策略,本篇博客将介绍如何通过NG... 目录1、简述2、实现方式3、使用 fail2ban 动态封禁3.1 安装 fail2ban3.2 配

MySQL 中的服务器配置和状态详解(MySQL Server Configuration and Status)

《MySQL中的服务器配置和状态详解(MySQLServerConfigurationandStatus)》MySQL服务器配置和状态设置包括服务器选项、系统变量和状态变量三个方面,可以通过... 目录mysql 之服务器配置和状态1 MySQL 架构和性能优化1.1 服务器配置和状态1.1.1 服务器选项

Vue3中的动态组件详解

《Vue3中的动态组件详解》本文介绍了Vue3中的动态组件,通过`component:is=动态组件名或组件对象/component`来实现根据条件动态渲染不同的组件,此外,还提到了使用`markRa... 目录vue3动态组件动态组件的基本使用第一种写法第二种写法性能优化解决方法总结Vue3动态组件动态

通俗易懂的Java常见限流算法具体实现

《通俗易懂的Java常见限流算法具体实现》:本文主要介绍Java常见限流算法具体实现的相关资料,包括漏桶算法、令牌桶算法、Nginx限流和Redis+Lua限流的实现原理和具体步骤,并比较了它们的... 目录一、漏桶算法1.漏桶算法的思想和原理2.具体实现二、令牌桶算法1.令牌桶算法流程:2.具体实现2.1

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操