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

相关文章

深度解析Nginx日志分析与499状态码问题解决

《深度解析Nginx日志分析与499状态码问题解决》在Web服务器运维和性能优化过程中,Nginx日志是排查问题的重要依据,本文将围绕Nginx日志分析、499状态码的成因、排查方法及解决方案展开讨论... 目录前言1. Nginx日志基础1.1 Nginx日志存放位置1.2 Nginx日志格式2. 499

go动态限制并发数量的实现示例

《go动态限制并发数量的实现示例》本文主要介绍了Go并发控制方法,通过带缓冲通道和第三方库实现并发数量限制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录带有缓冲大小的通道使用第三方库其他控制并发的方法因为go从语言层面支持并发,所以面试百分百会问到

使用zip4j实现Java中的ZIP文件加密压缩的操作方法

《使用zip4j实现Java中的ZIP文件加密压缩的操作方法》本文介绍如何通过Maven集成zip4j1.3.2库创建带密码保护的ZIP文件,涵盖依赖配置、代码示例及加密原理,确保数据安全性,感兴趣的... 目录1. zip4j库介绍和版本1.1 zip4j库概述1.2 zip4j的版本演变1.3 zip4

一文详解SpringBoot中控制器的动态注册与卸载

《一文详解SpringBoot中控制器的动态注册与卸载》在项目开发中,通过动态注册和卸载控制器功能,可以根据业务场景和项目需要实现功能的动态增加、删除,提高系统的灵活性和可扩展性,下面我们就来看看Sp... 目录项目结构1. 创建 Spring Boot 启动类2. 创建一个测试控制器3. 创建动态控制器注

Linux中压缩、网络传输与系统监控工具的使用完整指南

《Linux中压缩、网络传输与系统监控工具的使用完整指南》在Linux系统管理中,压缩与传输工具是数据备份和远程协作的桥梁,而系统监控工具则是保障服务器稳定运行的眼睛,下面小编就来和大家详细介绍一下它... 目录引言一、压缩与解压:数据存储与传输的优化核心1. zip/unzip:通用压缩格式的便捷操作2.

Java中的雪花算法Snowflake解析与实践技巧

《Java中的雪花算法Snowflake解析与实践技巧》本文解析了雪花算法的原理、Java实现及生产实践,涵盖ID结构、位运算技巧、时钟回拨处理、WorkerId分配等关键点,并探讨了百度UidGen... 目录一、雪花算法核心原理1.1 算法起源1.2 ID结构详解1.3 核心特性二、Java实现解析2.

springboot如何通过http动态操作xxl-job任务

《springboot如何通过http动态操作xxl-job任务》:本文主要介绍springboot如何通过http动态操作xxl-job任务的问题,具有很好的参考价值,希望对大家有所帮助,如有错... 目录springboot通过http动态操作xxl-job任务一、maven依赖二、配置文件三、xxl-

Go学习记录之runtime包深入解析

《Go学习记录之runtime包深入解析》Go语言runtime包管理运行时环境,涵盖goroutine调度、内存分配、垃圾回收、类型信息等核心功能,:本文主要介绍Go学习记录之runtime包的... 目录前言:一、runtime包内容学习1、作用:① Goroutine和并发控制:② 垃圾回收:③ 栈和

Java调用C#动态库的三种方法详解

《Java调用C#动态库的三种方法详解》在这个多语言编程的时代,Java和C#就像两位才华横溢的舞者,各自在不同的舞台上展现着独特的魅力,然而,当它们携手合作时,又会碰撞出怎样绚丽的火花呢?今天,我们... 目录方法1:C++/CLI搭建桥梁——Java ↔ C# 的“翻译官”步骤1:创建C#类库(.NET

MyBatis编写嵌套子查询的动态SQL实践详解

《MyBatis编写嵌套子查询的动态SQL实践详解》在Java生态中,MyBatis作为一款优秀的ORM框架,广泛应用于数据库操作,本文将深入探讨如何在MyBatis中编写嵌套子查询的动态SQL,并结... 目录一、Myhttp://www.chinasem.cnBATis动态SQL的核心优势1. 灵活性与可