494. 目标和

494. 目标和

  • 原题链接:
  • 完成情况:
  • 解题思路:
    • 数组回溯法
    • 动态规划
  • 参考代码:
    • 数组回溯法
    • __494目标和__动态规划
  • 经验吸取

原题链接:

494. 目标和

https://leetcode.cn/problems/target-sum/description/

完成情况:

在这里插入图片描述

解题思路:

数组回溯法

backTrack(nums, target, index+1, curSum+nums[index]);
backTrack(nums, target, index+1, curSum-nums[index]);

动态规划

	 假设P是正子集,N是负子集 例如: 假设nums = [1, 2, 3, 4, 5],target = 3,一个可能的解决方案是+1-2+3-4+5 = 3 这里正子集P = [1, 3, 5]和负子集N = [2, 4]
	 sum(P) - sum(N) = target
	 sum(P) + sum(N) + sum(P) - sum(N) = target + sum(P) + sum(N)
	 2 * sum(P) = target + sum(nums)
	 因此,原来的问题已转化为一个求子集的和问题: 找到nums的一个子集 P,使得sum(P) = (target + sum(nums)) / 2,该式已经证明了target + sum(nums)必须是偶数,否则无解
	 求子集的问题可以转化为01背包问题
	 定义二维数组dp,其中dp[i][j]表示在数组下标为0...i的元素中任选元素,使得这些元素之和等于j的方案数

在这里插入图片描述

在这里插入图片描述

参考代码:

数组回溯法

package 西湖算法题解___中等题;

public class __494目标和__数组回溯法 {
	int res = 0;
	public int findTargetSumWays(int[] nums, int target) {
		backTrack(nums,target,0,0);
		return res;
	}

	/**
	 *
	 * @param nums      数组
	 * @param target    目标值
	 * @param index     索引位置
	 * @param curSum    当前累计和
	 */
	private void backTrack(int[] nums, int target, int index, int curSum) {
		//1 <= nums.length <= 20
		//这种方法,属于递归,完全是因为数量级太小了
		//不然肯定算不出来的。
		if (index == nums.length){      //所有元素已经遍历完了
			if (curSum == target){
				res++;
			}
		}else{
			backTrack(nums, target, index+1, curSum+nums[index]);
			backTrack(nums, target, index+1, curSum-nums[index]);
		}
	}


}

__494目标和__动态规划

package 西湖算法题解___中等题;

public class __494目标和__评论区大佬 {
	/**
	 题目介绍:
	    就是说有一个数组,然后要在数组任意两两元素间插入一个【+】或者【-】
	    最终要构成target这个值,
	        问你有多少种拼接情况。
	 */
	public int findTargetSumWays(int[] nums, int target) {
		//很明显的一道dp题目,最终结果取决于过程叠加。
		/**
		 假设P是正子集,N是负子集 例如: 假设nums = [1, 2, 3, 4, 5],target = 3,一个可能的解决方案是+1-2+3-4+5 = 3 这里正子集P = [1, 3, 5]和负子集N = [2, 4]
		 sum(P) - sum(N) = target
		 sum(P) + sum(N) + sum(P) - sum(N) = target + sum(P) + sum(N)
		 2 * sum(P) = target + sum(nums)
		 因此,原来的问题已转化为一个求子集的和问题: 找到nums的一个子集 P,使得sum(P) = (target + sum(nums)) / 2,该式已经证明了target + sum(nums)必须是偶数,否则无解
		 求子集的问题可以转化为01背包问题
		 定义二维数组dp,其中dp[i][j]表示在数组下标为0...i的元素中任选元素,使得这些元素之和等于j的方案数
		 */
		int nLength = nums.length;
		//先去掉点特殊情况
		int sum = 0;
		for (int num:nums){
			sum += num;
		}
		// target + sum(nums)必须是偶数,否则无解     //要使target = nums[]的加减操作合,则它们必须同奇或者同偶
		// Math.abs(target) <= sum才有解       //目标值不能比绝对值求和还大
		//偶数判断还可以用   (lambda & 1) == 1   去判断
		if (((sum + target) & 1) == 1 || Math.abs(target) > sum){
			return 0;
		}
		int size = (sum + target) / 2;

		// 定义二维数组dp,其中dp[i][j]表示在数组下标为0...i的元素中任选元素,使得这些元素之和等于j的方案数
		int dp_findTargetSumWays [][] = new int[nLength][size+1];
		// 对dp[0][j]的初始化:除dp[0][0]和dp[0][nums[0]]外全部初始化为0
		// dp[0][0] = 1:nums[0]不为0时,此时dp[0][0]和dp[0][nums[0]]不重合,只有不选nums[0],其总和为0
		// dp[0][0] = 2:nums[0]为0时,此时dp[0][0]和dp[0][nums[0]]重合,选或者不选nums[0],其总和都为0
		if (nums[0] <= size){
			dp_findTargetSumWays[0][nums[0]] = 1;
		}
		if (nums[0] == 0){
			dp_findTargetSumWays[0][0] = 2;
		}else {
			dp_findTargetSumWays[0][0] = 1;
		}

		// 对dp[i][0]的初始化,可以放在下面整个dp的递推代码中
		for (int i = 1;i<nLength;i++){
			if (nums[i] == 0){
				//当nums[1]为0时,选择或者不选择nums[1]都可以使总和为0,
				//即dp[i][0] = dp[i - 1][0] + dp[i - 1][0 - nums[i]] = 2 * dp[i -1][0]
				dp_findTargetSumWays[i][0] = 2*dp_findTargetSumWays[i-1][0];
			}else{
				// 当nums[i]不为0时,只有不选nums[i]才可以使总和为0
				dp_findTargetSumWays[i][0] = dp_findTargetSumWays[i-1][0];
			}
		}
		// dp[i][j]递推:由于初始化时都将i = 0和j = 0的情况已经赋值,所以直接从i = 1和j = 1开始
		// 完全可以将上面对dp[i][0]的初始化放在此处,只需要将j从0开始
		for (int i=1;i<nLength;i++){
			for (int j=1;j<=size;j++){
				if (j>=nums[i]){
					dp_findTargetSumWays[i][j] = dp_findTargetSumWays[i-1][j] + dp_findTargetSumWays[i-1][j-nums[i]];
				}else{
					dp_findTargetSumWays[i][j] = dp_findTargetSumWays[i-1][j];
				}
			}
		}
		return dp_findTargetSumWays[nLength-1][size];
	}
}

经验吸取

  1. 首先,如果最终结果可以由其中的每一步过程,造成影响得来,那么就可以考虑用dp

  2. dp的难点就在于状态转移方程!!!如何将一个问题转化很重要!!!

  3. 转化形式应该为:
    在这里插入图片描述
    未知状态 = 已知确定目标值
    在这里插入图片描述

    dp数组过程推演情况。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

openCV使用c#操作摄像头

效果如下&#xff1a; 1.创建一个winform的窗体项目&#xff08;框架.NET Framework 4.7.2&#xff09; 2.Nuget引入opencv的c#程序包&#xff08;版本最好和我一致&#xff09; 3.后台代码 using System; using System.Collections.Generic; using System.ComponentModel;…

Redis系列(三):深入解读Redis主从同步机制

首发博客地址 https://blog.zysicyj.top/ Redis高可靠靠什么保证&#xff1f; 为什么要提这个呢&#xff0c;因为Redis主从库目的呢其实就是为了实现高可靠。上篇文章中我们说过Redis的AOF、RDB日志其实就是为了减少数据丢失&#xff0c;这是高可靠的一部分。 这篇文章呢&#…

爬虫逆向实战(六)--猿人学第四题

一、数据接口分析 主页地址&#xff1a;猿人学第四题 1、抓包 通过抓包可以发现数据接口是api/match/4 2、判断是否有加密参数 请求参数是否加密&#xff1f; 无请求头是否加密&#xff1f; 无响应是否加密&#xff1f; 响应数据无加密&#xff0c;但是返回的却是html代码…

展会邀请 | 虹科诚邀您参加8月16日深圳视觉系统设计技术会议

VisionCon视觉系统设计技术会议 将于8月16日在深圳深铁皇冠假日酒店隆重举行&#xff01; 人力成本的提高、国际关系的不确定性等众多因素&#xff0c;都在促使中国制造业采用更先进的自动化及智能化技术&#xff0c;同时也在加速核心技术的国产化。作为智能制造不可或缺的关…

Ubuntu中安装OpenSSL

文章目录 一、前期准备1.1 压缩包下载1.2 gcc, make等的安装二、安装配置 一、前期准备 1.1 压缩包下载 在安装openssl之前&#xff0c;我们需要下载对应的压缩包 https://www.openssl.org/source/openssl-3.0.1.tar.gz 此压缩包可以选择win上下载后解压再复制到本地虚拟机中…

Linux 基础命令

文件系统 Linux文件系统结构与Windows有些不同。Linux在文件系统的基础上没有物理驱动器&#xff08;例如C&#xff1a;驱动器&#xff09;&#xff0c; 而是使用逻辑文件系统。在文件系统结构的最顶层是/&#xff0c;它通常被称为文件系统的根&#xff0c;就好像它是一个倒置 …

从零开始打造家装预约咨询小程序

在如今互联网高度发达的时代&#xff0c;家装行业也逐渐意识到了线上渠道的重要性。为了更好地服务客户&#xff0c;提高用户体验&#xff0c;越来越多的家装公司开始寻找合适的小程序制作平台。本文将向大家介绍如何使用第三方制作平台&#xff0c;如乔拓云网&#xff0c;打造…

KBEngine增加ThinkingData打点

Windows下的安装ThinkingData 首先根据他的文档&#xff0c;安装sdk和Logbus&#xff0c;他的原理是sdk写入到log文件&#xff0c;然后通过Logbus2来传送到TD&#xff08;ThinkingData&#xff09;服务器。 通过pip获取 Python SDK pip install ThinkingDataSdk pip install…

Python爬虫——scrapy_当当网图书管道封装

创建爬虫项目 srcapy startproject scrapy_dangdang进入到spider文件里创建爬虫文件&#xff08;这里爬取的是青春文学&#xff0c;仙侠玄幻分类&#xff09; srcapy genspider dang http://category.dangdang.com/cp01.01.07.00.00.00.html获取图片、名字和价格 # 所有的se…

leetcode-413. 等差数列划分(java)

等差数列划分 leetcode-413. 等差数列划分题目描述双指针 上期经典算法 leetcode-413. 等差数列划分 难度 - 中等 原题链接 - 等差数列划分 题目描述 如果一个数列 至少有三个元素 &#xff0c;并且任意两个相邻元素之差相同&#xff0c;则称该数列为等差数列。 例如&#xff0…

图数据库_Neo4j基于docker服务版安装_Neo4j Desktop桌面版安装---Neo4j图数据库工作笔记0004

然后我们来看看如何用docker来安装Neo4j community server 首先去执行docker pull neo4j:3.5.22-community 去拉取镜像 然后执行命令就可以安装了 可以用docker ps查看一下 看看暴露了哪些端口 然后再看一下访问一下这个时候,要用IP地址了注意 然后再来看一下安装Desktop 去下…

DAMO-YOLO:实时目标检测设计的报告

ReadPaperhttps://readpaper.com/pdf-annotate/note?pdfId4748421678288076801eId1920373270663763712 Abstract 在本报告中&#xff0c;我们提出了一种快速准确的目标检测方法&#xff0c;称为DAMO-YOLO&#xff0c;它比最先进的YOLO系列实现了更高的性能。DAMO-YOLO 通过…

R语言实现神经网络(1)

#R语言实现神经网络 library(neuralnet) library(caret) library(MASS) library(vcd) data(shuttle) str(shuttle)#因变量use; table1<-structable(windmagn~use,shuttle) mosaic(table1,shadingT) mosaic(use~errorvis,shuttle) prop.table(table(shuttle$use,shuttle$stab…

第十一课:Qt 快捷键大全

功能描述&#xff1a;Qt 中的快捷键查看方式和自定义快捷键 一、快捷键查看/自定义 Qt Creator 中提供了各种快捷键&#xff0c;如需查看或自定义快捷键&#xff0c;选择菜单栏“工具” -> “选项” -> “环境” -> “键盘”。 快捷键按类别列出&#xff0c;可以在过…

C++提高编程——模板

C提高编程 本阶段主要针对C泛型编程和STT技术做详细讲解&#xff0c;探讨C更深层的使用 1模板 1.1模板的概念 模板就是建立通用的模具&#xff0c;大大提高复用性 例如生活中的模板 寸照片模板&#xff1a; 1.2函数模板 C另一种编程思想称为 泛型编程&#xff0c;主要利…

【回溯】总结

1、 组合和子集问题 组合问题需要满足一定要求才算作一个答案&#xff0c;比如数量要求&#xff08;k个数&#xff09;&#xff0c;累加和要求&#xff08;target&#xff09;。 子集问题是只要构成一个新的子集就算作一个答案。 进阶&#xff1a;去重逻辑。 一般都是要对同…

QT学习笔记-Linux ARM环境下实现QT程序通过ODBC驱动访问SQLServer数据库

QT学习笔记-Linux ARM环境下实现QT程序通过ODBC驱动访问SQLServer数据库 0、背景1、基本环境2、搭建交叉编译环境3、在交叉编译服务器上交叉编译安装unixODBC3.1 下载unixODBC3.2 交叉编译unixODBC3.2.1 基本编译说明3.2.2 交叉编译说明3.2.3 ./configure -build,-host,-target…

Android Ble蓝牙App(五)数据操作

Ble蓝牙App&#xff08;五&#xff09;数据操作 前言目录正文一、操作内容处理二、读取数据① 概念② 实操 三、写入数据① 概念② 实操 四、打开通知一、概念二、实操三、收到数据 五、源码 前言 关于低功耗蓝牙的服务、特性、属性、描述符都已经讲清楚了&#xff0c;而下面就…

golang—面试题大全

目录标题 sliceslice和array的区别slice扩容机制slice是否线程安全slice分配到栈上还是堆上扩容过程中是否重新写入go深拷贝发生在什么情况下&#xff1f;切片的深拷贝是怎么做的copy和左值进行初始化区别slice和map的区别 mapmap介绍map的key的类型map对象如何比较map的底层原…

6939. 数组中的最大数对和

题目描述&#xff1a; 给你一个下标从 0 开始的整数数组 nums 。请你从 nums 中找出和 最大 的一对数&#xff0c;且这两个数数位上最大的数字相等。 返回最大和&#xff0c;如果不存在满足题意的数字对&#xff0c;返回 -1 。 示例&#xff1a; 解题思路&#xff1a; 使用数组…