leetCode 494. 目标和 + 动态规划 + 记忆化搜索 + 递推 + 空间优化

news2024/11/26 4:29:42

关于本题我的往期文章:

LeetCode 494.目标和 (动态规划 + 性能优化)二维数组 压缩成 一维数组_呵呵哒( ̄▽ ̄)"的博客-CSDN博客icon-default.png?t=N7T8https://heheda.blog.csdn.net/article/details/133253822


给你一个非负整数数组 nums 和一个整数 target 。向数组中的每个整数前添加 '+' 或 '-' ,然后串联起所有整数,可以构造一个 表达式 :

  • 例如,nums = [2, 1] ,可以在 2 之前添加 '+' ,在 1 之前添加 '-' ,然后串联起来得到表达式 "+2-1" 。

返回可以通过上述方法构造的、运算结果等于 target 的不同 表达式 的数目。


(1)递归 

class Solution {
public:
    // 递归
    int findTargetSumWays(vector<int>& nums, int target) {
        int sum=0,n=nums.size();
        for(const int & x:nums) sum+=x;
        if (abs(target) > sum) return 0; // 此时没有方案
        if ((sum + target) % 2 == 1) return 0; // 此时没有方案
        if ((sum + target) % 2 == 1) return 0; // 此时没有方案
        int addTarget = (sum + target) / 2;
        function<int(int,int)> dfs = [&](int i,int c) -> int {
            if(i<0) return c==0 ? 1 : 0;// 边界条件:由于要求是恰好组成。恰好情况:当c=0的时候,才能返回1,表示这是一个合法的方案
            if(c-nums[i]<0) return dfs(i-1,c);
            return dfs(i-1,c) + dfs(i-1,c-nums[i]);
        };
        return dfs(n-1,addTarget);
    }
};

(2)递归搜索 + 保存计算结果 = 记忆化搜索

class Solution {
public:
    // 记忆化搜索
    int findTargetSumWays(vector<int>& nums, int target) {
        int sum=0,n=nums.size();
        for(const int & x:nums) sum+=x;
        if (abs(target) > sum) return 0; // 此时没有方案
        if ((sum + target) % 2 == 1) return 0; // 此时没有方案
        int addTarget = (sum + target) / 2;
        vector<vector<int>> memo(n+1,vector<int>(addTarget+1,-1));
        function<int(int,int)> dfs = [&](int i,int c) -> int {
            if(i<0) return c==0 ? 1 : 0;
            int &res = memo[i][c];
            if(res != -1) return res;
            if(c-nums[i]<0) return res=dfs(i-1,c);
            return res=dfs(i-1,c) + dfs(i-1,c-nums[i]);
        };
        return dfs(n-1,addTarget);
    }
};

(3)1:1 翻译递推

  • dfs(i,c) = dfs(i-1,c) + dfs(i-1,c-w[i])
  • f[i][c] = f[i-1][c] + f[i-1][c-w[i]]
  • f[i+1][c] = f[i][c] + f[i][c-w[i]]

初始化:根据 if(i<0) return c==0 ? 1 : 0; 

  • f 数组初始化为 0
  • dfs(-1,0) = 1 翻译f[0][0]=1

返回最终结果:根据 dfs(n-1,addTarget) 翻译 f[n][addTarget] 

class Solution {
public:
    // 递推式
    int findTargetSumWays(vector<int>& nums, int target) {
        int sum=0,n=nums.size();
        for(const int & x:nums) sum+=x;
        if (abs(target) > sum) return 0; // 此时没有方案
        if ((sum + target) % 2 == 1) return 0; // 此时没有方案
        int addTarget = (sum + target) / 2;
        vector<vector<int>> f(n+1,vector<int>(addTarget+1,0));
        f[0][0]=1;
        for(int i=0;i<n;i++) {
            for(int c=0;c<=addTarget;c++) {
                if(c-nums[i]<0) f[i+1][c]=f[i][c];
                else f[i+1][c]=f[i][c] + f[i][c-nums[i]];
            }
        }
        return f[n][addTarget];
    }
};

  • 优化空间

方式一:二维数组优化

  • f[(i+1)%2][c]=f[i%2][c] + f[i%2][c-nums[i]];
class Solution {
public:
    // 递推式 + 优化空间
    int findTargetSumWays(vector<int>& nums, int target) {
        int sum=0,n=nums.size();
        for(const int & x:nums) sum+=x;
        if (abs(target) > sum) return 0; // 此时没有方案
        if ((sum + target) % 2 == 1) return 0; // 此时没有方案
        int addTarget = (sum + target) / 2;
        vector<vector<int>> f(2,vector<int>(addTarget+1,0));
        f[0][0]=1;
        for(int i=0;i<n;i++) {
            for(int c=0;c<=addTarget;c++) {
                if(c-nums[i]<0) f[(i+1)%2][c]=f[i%2][c];
                else f[(i+1)%2][c]=f[i%2][c] + f[i%2][c-nums[i]];
            }
        }
        return f[n%2][addTarget];
    }
};

方式二:一维数组优化

  • f[i+1][c]=f[i][c] + f[i][c-nums[i]];
  • f[c]=f[c] + f[c-nums[i]];
class Solution {
public:
    // 递推式 + 优化空间
    int findTargetSumWays(vector<int>& nums, int target) {
        int sum=0,n=nums.size();
        for(const int & x:nums) sum+=x;
        if (abs(target) > sum) return 0; // 此时没有方案
        if ((sum + target) % 2 == 1) return 0; // 此时没有方案
        int addTarget = (sum + target) / 2;
        vector<int>f(addTarget+1,0);
        f[0]=1;
        for(int i=0;i<n;i++) {
            for(int c=addTarget;c>=nums[i];c--) {
                f[c]=f[c] + f[c-nums[i]];
            }
        }
        return f[addTarget];
    }
};


// 也可以写成这样
for(const int& x:nums) {
    for(int c=addTarget;c>=x;c--) {
        f[c]=f[c] + f[c-x];
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1170773.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

从lc114. 二叉树展开为链表到lc-LCR 155二叉搜索树转化为排序的双向链表

1 lc114. 二叉树展开为链表 1.1 描述 进阶&#xff1a;你可以使用原地算法&#xff08;O(1) 额外空间&#xff09;展开这棵树吗&#xff1f; 1.2 解法一&#xff1a; 先序遍历这棵树并且将节点加入到一个list中&#xff0c;随后按顺序将list中的每一个元素的left指针置换为…

如何保证消息只被消费一次

目录 前言 一、什么是幂等&#xff1f; 二、在生产过程中增加消息幂等性的保证 三、在消费过程中增加消息幂等性的保证 前言 消息一旦被重复消费&#xff0c;就会造成业务逻辑处理的错误。那么我们要如何避免消息的重复呢&#xff1f; 想要完全的避免消息重复的发生是很难…

全方位移动机器人 SolidWorks 转 URDF 并在 Rviz 中仿真

全方位移动机器人 SolidWorks 转 URDF 并在 Rviz 中仿真 参考 solidworks转URDF&#xff0c;并且在rviz中仿真 从solidworks导出URDF模型 Export a SolidWorks Assembly to URDF Solidworks模型导出urdf SolidWorks 模型简化 将整车除车轮部分另存为零件&#xff0c;作为一个…

MySQL连接时出现Host ‘::1‘ is not allowed to connect to this MySQL server

报错原因 之前想着要提高一下连接速度&#xff0c;所以在my.ini中加入了&#xff1a;skip-name-resolve&#xff0c;当时的数据库root账号设置的登录权限是%&#xff0c;因此没有出现连接错误&#xff0c;这次因为是新建数据库&#xff0c;root账号的登录权限默认是localhost&…

如何基于链表与数组实现栈

这里写目录标题 栈的基础知识基于数组实现栈基于链表实现栈 栈的基础知识 栈&#xff0c;又名堆栈&#xff0c;是一种受限的线性表&#xff0c;这意味着该线性表只能在一段进行插入或删除操作。具体来说&#xff0c;栈顶是允许进行插入或删除操作的一端&#xff0c;而相对的另…

零基础入门网络安全白帽黑客,挑战年薪30w!

最近好朋友老李说他想转渗透测试。 他说&#xff1a;运维这块干了3年了&#xff0c;感觉自己目前有点迷茫&#xff0c;不知该怎么去提升了。而在日常工作生活当中&#xff0c;黑客攻击可以说是很常见了&#xff0c;他感觉到网络安全越来越重要&#xff0c;对软件测试的要求也不…

大疆Livox MID-360安装ROS1/2驱动 Ubuntu20.04

文章目录 一、接线连接二、安装上位机可视化工具三、安装ROS驱动3.1 配置静态IP3.2 安装Livox SDK23.3 安装ROS驱动3.4 驱动 本文介绍如何在Ubuntu20.04中安装大疆Livox MID-360的ROS1/2驱动 一、接线连接 livox航插一分三线&#xff0c;其中航空母头连接激光雷达&#xff0c…

Spring | Sring Task (定时任务框架) 、微信小程序开发

目录&#xff1a; 一、Sring Task (定时任务框架) &#xff1a;Sring Task介绍Spring Task应用场景corn表达式corn表达式在线生成器SpringTask入门案例&#xff1a;导入maven依赖启动类上添加 EnableScheduling 注解定时方法上添加 Scheduled( cron “xxxxx” ) 注解自定义“定…

ZKP Introduction of Nova (Yu Guo) 手写笔记

ZKP学习笔记 郭宇老师Nova课程手写笔记

创建asp.net api和docker-compose项目

vs2022创建asp.net core web api项目 创建完成 添加docker-compose支持 添加成功 docker配置 docker-compose配置

腾讯云3年轻量2核2G4M服务器从366.6元三年涨价了?

2023腾讯云双11优惠活动3年轻量应用服务器涨价了&#xff1f;确实是涨价了&#xff0c;仅限于三年时长轻量应用服务器&#xff0c;一年时长并没有涨价&#xff0c;相比隔壁阿里云&#xff0c;腾讯云依旧在提供三年轻量应用服务器和5年时长云服务器CVM已经很难得了&#xff0c;想…

集线器、交换机、网桥、路由器、网关

目录 集线器(HUB)交换机(SWITCH)网桥(BRIDGE)路由器(ROUTER)网关(GATEWAY)交换机和路由器的区别参考 集线器(HUB) 功能 集线器对数据的传输起到同步、放大和整形的作用 属于物理层设备 工作机制 使用集线器互连而成的以太网被称为共享式以太网。当某个主机要给另一个主机发送单…

如何使用 SwiftUI 中新地图框架 MapKit

文章目录 前言MapKit 弃用项MapContentBuilder&#xff08;iOS 17&#xff09;地图交互地图样式地图控件地图相机位置总结 前言 了解 iOS 17 中的 MapKit 后&#xff0c;我们会发现 Apple 引入了更适合 SwiftUI 的 API。 MapKit 弃用项 一旦将你的 App 目标更新到 iOS 17&am…

OpenGL ES入门教程(二)之绘制一个平面桌子

OpenGL ES入门教程&#xff08;二&#xff09;之绘制一个平面桌子 前言0. OpenGL绘制图形的整体框架概述1. 定义顶点2. 定义着色器3. 加载着色器4. 编译着色器5. 将着色器链接为OpenGL程序对象6. 将着色器需要的数据与拷贝到本地的数组相关联7. 在屏幕上绘制图形8. 让桌子有边框…

立创eda 焊接辅助工具使用

立创EDA为板级EDA设计软件。EDA指的是通过计算机的辅助完成电路原理图、印刷电路板文件等的绘制、制作、仿真设计。 立创EDA是一款基于浏览器的&#xff0c;专为中国人设计的&#xff0c;友好易用的EDA设计工具。起于2010年&#xff0c;完全由中国人独立开发&#xff0c;拥有独…

Ubuntu下安装vscode,并解决终端打不开vscode的问题

Visual Studio Code安装 1&#xff0c;使用 apt 安装 Visual Studio Code 在官方的微软 Apt 源仓库中可用。按照下面的步骤进行即可&#xff1a; 以 sudo 用户身份运行下面的命令&#xff0c;更新软件包索引&#xff0c;并且安装依赖软件&#xff1a; sudo apt update sud…

女孩子穿这种粉粉嫩嫩~的卫衣也太好看了吧

果然女孩子穿这种粉粉嫩嫩的衣服 真的超级有甜美可爱氛围哎 软糯亲肤的面料&#xff0c;上身很舒服哦 时尚polo领加上半拉链设计 既实用又美观&#xff0c;穿脱很方便

如何使用Selenium处理Cookie,今天彻底学会了!

01、cookie介绍 HTTP协议是无状态的协议。一旦数据交换完毕&#xff0c;客户端与服务器端的连接就会关闭&#xff0c;再次交换数据需要建立新的连接&#xff0c;这就意味着服务器无法从连接上跟踪会话。也就是说即使第一次和服务器连接后并且登录成功后&#xff0c;第二次请求…

进程终止(不同情况+如何查看:strerror,echo $?),终止的方法(return,exit,_exit),exit和_exit的不同

目录 进程终止 进程终止是什么 进程终止的情况 代码跑完,结果正确/不正确 提前知道结果 不知道结果 strerror 示例 -- echo $? 代码未跑完,程序崩溃 示例 进程退出方法 return退出码 exit(status) _exit(status) exit()和_exit()的不同 示例 缓冲区位置 进…

华为云RDS数据库(Mysql)不买公网IP无法Navicate连接

前言 最近公司有一个项目甲方为了便宜购买了华为云的ECS服务器与RDS云数据库&#xff08;Mysql&#xff09;进行项目部署&#xff0c;实际部署数据库时发现&#xff0c;华为云的数据库需要购买公网IP才能使用Navicate连接数据库&#xff08;不可思议的我还提交工单确认了一下以…