【算法学习笔记】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

相关文章

openCV中KNN算法的实现

《openCV中KNN算法的实现》KNN算法是一种简单且常用的分类算法,本文主要介绍了openCV中KNN算法的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录KNN算法流程使用OpenCV实现KNNOpenCV 是一个开源的跨平台计算机视觉库,它提供了各

SpringSecurity JWT基于令牌的无状态认证实现

《SpringSecurityJWT基于令牌的无状态认证实现》SpringSecurity中实现基于JWT的无状态认证是一种常见的做法,本文就来介绍一下SpringSecurityJWT基于令牌的无... 目录引言一、JWT基本原理与结构二、Spring Security JWT依赖配置三、JWT令牌生成与

MySQL中动态生成SQL语句去掉所有字段的空格的操作方法

《MySQL中动态生成SQL语句去掉所有字段的空格的操作方法》在数据库管理过程中,我们常常会遇到需要对表中字段进行清洗和整理的情况,本文将详细介绍如何在MySQL中动态生成SQL语句来去掉所有字段的空... 目录在mysql中动态生成SQL语句去掉所有字段的空格准备工作原理分析动态生成SQL语句在MySQL

利用Python快速搭建Markdown笔记发布系统

《利用Python快速搭建Markdown笔记发布系统》这篇文章主要为大家详细介绍了使用Python生态的成熟工具,在30分钟内搭建一个支持Markdown渲染、分类标签、全文搜索的私有化知识发布系统... 目录引言:为什么要自建知识博客一、技术选型:极简主义开发栈二、系统架构设计三、核心代码实现(分步解析

Java图片压缩三种高效压缩方案详细解析

《Java图片压缩三种高效压缩方案详细解析》图片压缩通常涉及减少图片的尺寸缩放、调整图片的质量(针对JPEG、PNG等)、使用特定的算法来减少图片的数据量等,:本文主要介绍Java图片压缩三种高效... 目录一、基于OpenCV的智能尺寸压缩技术亮点:适用场景:二、JPEG质量参数压缩关键技术:压缩效果对比

Java调用C++动态库超详细步骤讲解(附源码)

《Java调用C++动态库超详细步骤讲解(附源码)》C语言因其高效和接近硬件的特性,时常会被用在性能要求较高或者需要直接操作硬件的场合,:本文主要介绍Java调用C++动态库的相关资料,文中通过代... 目录一、直接调用C++库第一步:动态库生成(vs2017+qt5.12.10)第二步:Java调用C++

springboot+dubbo实现时间轮算法

《springboot+dubbo实现时间轮算法》时间轮是一种高效利用线程资源进行批量化调度的算法,本文主要介绍了springboot+dubbo实现时间轮算法,文中通过示例代码介绍的非常详细,对大家... 目录前言一、参数说明二、具体实现1、HashedwheelTimer2、createWheel3、n

关于WebSocket协议状态码解析

《关于WebSocket协议状态码解析》:本文主要介绍关于WebSocket协议状态码的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录WebSocket协议状态码解析1. 引言2. WebSocket协议状态码概述3. WebSocket协议状态码详解3

SpringBoot3实现Gzip压缩优化的技术指南

《SpringBoot3实现Gzip压缩优化的技术指南》随着Web应用的用户量和数据量增加,网络带宽和页面加载速度逐渐成为瓶颈,为了减少数据传输量,提高用户体验,我们可以使用Gzip压缩HTTP响应,... 目录1、简述2、配置2.1 添加依赖2.2 配置 Gzip 压缩3、服务端应用4、前端应用4.1 N

C#如何动态创建Label,及动态label事件

《C#如何动态创建Label,及动态label事件》:本文主要介绍C#如何动态创建Label,及动态label事件,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C#如何动态创建Label,及动态label事件第一点:switch中的生成我们的label事件接着,