LeetCode——动态规划(三)

刷题顺序及思路来源于代码随想录,网站地址:https://programmercarl.com 

目录

494. 目标和 - 力扣(LeetCode)

474. 一和零 - 力扣(LeetCode)

518. 零钱兑换 II - 力扣(LeetCode)

377. 组合总和 Ⅳ - 力扣(LeetCode)

70. 爬楼梯 - 力扣(LeetCode)


 

494. 目标和 - 力扣(LeetCode)

给你一个非负整数数组 nums 和一个整数 target 。

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

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

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

输入:nums = [1,1,1,1,1], target = 3
输出:5
解释:一共有 5 种方法让最终目标和为 3 。
-1 + 1 + 1 + 1 + 1 = 3
+1 - 1 + 1 + 1 + 1 = 3
+1 + 1 - 1 + 1 + 1 = 3
+1 + 1 + 1 - 1 + 1 = 3
+1 + 1 + 1 + 1 - 1 = 3
import java.util.Scanner;

/**
 * @author light
 * @Description 目标和
 *
 *(思路:可以将数组分为两部分left和right,
 * 即有left-right=target;
 * 又有left+right=sum;
 * 转化为left=(sum+target)/2
 * 所以有两个解法---1.回溯求目标和;2.转化维持01背包问题---背包容量为left;
 * @create 2023-09-26 10:13
 */
public class FindTargetSumWaysTest {
	public static void main(String[] args) {
		Scanner input=new Scanner(System.in);
		int n= input.nextInt();
		int[] nums=new int[n];
		for (int i = 0; i < n; i++) {
			nums[i]=input.nextInt();
		}
		int target=input.nextInt();
		System.out.println(findTargetSumWays(nums, target));
	}
	public static int findTargetSumWays(int[] nums, int target) {
		int sum=0;
		for (int num : nums) {
			sum+=num;
		}
		if(Math.abs(target)>sum){
			return  0; //找不到组合
		}
		int left=(sum+target)/2;
		if((sum+target)%2!=0){
			return 0; //找不到组合
		}

		//动规
		//dp[j]:装满容量为j的背包共有dp[j]种方法
		int[] dp=new int[left+1];
		dp[0]=1;
		for (int i = 0; i < nums.length; i++) { //先遍历物品
			for(int j=left;j>=nums[i];j--){ //再遍历背包
				dp[j]+=dp[j-nums[i]];
			}

		}
		return dp[left];
	}
}

474. 一和零 - 力扣(LeetCode)

给你一个二进制字符串数组 strs 和两个整数 m 和 n 。

请你找出并返回 strs 的最大子集的长度,该子集中 最多 有 m 个 0 和 n 个 1 。

如果 x 的所有元素也是 y 的元素,集合 x 是集合 y 的 子集 。

输入:strs = ["10", "0001", "111001", "1", "0"], m = 5, n = 3
输出:4
解释:最多有 5 个 0 和 3 个 1 的最大子集是 {"10","0001","1","0"} ,因此答案是 4 。
其他满足题意但较小的子集包括 {"0001","1"} 和 {"10","1","0"} 。{"111001"} 不满足题意,因为它含 4 个 1 ,大于 n 的值 3 。
import java.util.Scanner;

/**
 * @author light
 * @Description 一和零
 * 给你一个二进制字符串数组 strs 和两个整数 m 和 n 。
 *
 * 请你找出并返回 strs 的最大子集的长度,该子集中 最多 有 m 个 0 和 n 个 1 。
 *
 * 如果 x 的所有元素也是 y 的元素,集合 x 是集合 y 的 子集 。
 *
 * (思路:转化为01背包问题
 * @create 2023-09-26 10:58
 */
public class FindMaxFormTest {
	public static void main(String[] args) {
		Scanner input=new Scanner(System.in);
		String[] strs=input.next().split(",");
		int m=input.nextInt();
		int n=input.nextInt();
		System.out.println(findMaxForm(strs, m, n));
	}
	public static int findMaxForm(String[] strs, int m, int n) {
		//dp[i][j]:最多有i个0,j个1的str的最大子集长度为dp[i][j]
		int[][] dp=new int[m+1][n+1];
		int zeroNum;
		int oneNum;
		dp[0][0]=0;
		//遍历物品
		for (String str : strs) {
			zeroNum=0;
			oneNum=0;
			for (int i = 0; i <str.length(); i++) {
				char ch=str.charAt(i);
				if(ch=='0'){
					zeroNum++;
				}else {
					oneNum++;
				}
			}
			//倒叙遍历---遍历背包
			for (int i =m; i >=zeroNum ; i--) {
				for (int j = n; j >=oneNum; j--) {
					dp[i][j]=Math.max(dp[i][j],dp[i-zeroNum][j-oneNum]+1);
				}
			}
		}
		return dp[m][n];
	}
}

518. 零钱兑换 II - 力扣(LeetCode)

给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。

请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。

假设每一种面额的硬币有无限个。 

题目数据保证结果符合 32 位带符号整数。

输入:amount = 5, coins = [1, 2, 5]
输出:4
解释:有四种方式可以凑成总金额:
5=5
5=2+2+1
5=2+1+1+1
5=1+1+1+1+1

/**
 * @author light
 * @Description 零钱兑换II
 * 
 * (思路:转化为完全背包问题
 * @create 2023-09-26 11:45
 */
public class ChangeTest {
	public int change(int amount, int[] coins) {
		//dp[j]:凑成总金额为j的硬币组合数为dp[j]
		int[] dp=new int[amount+1];
		dp[0]=1;
		for (int i = 0; i < coins.length; i++) {
			for (int j = coins[i]; j <=amount; j++) {
				dp[j]+=dp[j-coins[i]];
			}

		}
		return dp[amount];

	}
}

377. 组合总和 Ⅳ - 力扣(LeetCode)

给你一个由 不同 整数组成的数组 nums ,和一个目标整数 target 。请你从 nums 中找出并返回总和为 target 的元素组合的个数。

题目数据保证答案符合 32 位整数范围。

输入:nums = [1,2,3], target = 4
输出:7
解释:
所有可能的组合为:
(1, 1, 1, 1)
(1, 1, 2)
(1, 2, 1)
(1, 3)
(2, 1, 1)
(2, 2)
(3, 1)
请注意,顺序不同的序列被视作不同的组合。
/**
 * @author light
 * @Description 组合总和IV

 * 请注意,顺序不同的序列被视作不同的组合。---相当于求排列
 * (思路:转化为完全背包问题,对于排列问题,先遍历背包,在遍历物品
 * @create 2023-09-26 12:23
 */
public class CombinationSum4Test {

	public int combinationSum4(int[] nums, int target) {
		//dp[j]:总和为j的背包的元素排列个数为dp[j]
		int[] dp=new int[target+1];
		dp[0]=1;
		for (int i = 0; i <=target ; i++) { //先背包
			for (int j = 0; j < nums.length; j++) { //在物品
				if(i>=nums[j]){
					dp[i]+=dp[i-nums[j]];
				}
			}
		}
		return dp[target];
	}
}

70. 爬楼梯 - 力扣(LeetCode)

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

 升级:
 改为:一步一个台阶,两个台阶,三个台阶,.......,直到 m个台阶。
问有多少种不同的方法可以爬到楼顶呢?

输入:n = 2
输出:2
解释:有两种方法可以爬到楼顶。
1. 1 阶 + 1 阶
2. 2 阶

/**
 * @author light
 * @Description 爬楼梯进阶版

 *
 * (思路:
 * 1阶,2阶,.... m阶就是物品,楼顶就是背包。
 *
 * 每一阶可以重复使用,例如跳了1阶,还可以继续跳1阶。
 *
 * 问跳到楼顶有几种方法其实就是问装满背包有几种方法。
 *
 *这就是一个完全背包问题了
 * @create 2023-09-26 14:54
 */
public class ClimbStairsProTest {
	public int climbStairs(int n,int m) {
		//dp[i]:爬到第i阶楼梯共有dp[i]种方法
		int[] dp=new int[n+1];
		dp[0]=1;
		for (int i = 1; i <=n ; i++) { //先背包
			for (int j = 1; j <=m; j++) { //再物品
				if(i>=j){
					dp[i]+=dp[i-j];
				}
			}
		}
		return dp[n];
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
插件名字叫leetcode editor,可以解决在上班时想刷leetcode但又不想直接打开leetcode界面太扎眼或者无法debug的问题。你可以在IDEA的plugins中搜索并下载leetcode editor插件。 插件的下载地址是https://plugins.jetbrains.com/plugin/12132-leetcode-editor。 下载并安装插件后,你可以在IDEA的File -> Settings -> Tools -> Leetcode Plugin***com作为网址选项。此外,你还可以选择代码类型,包括Java、Python、C、Python3、C、C#、JavaScript、Ruby、Swift、Go、Scala、Kotlin、Rust、PHP。你需要输入登录名和密码来登录leetcode账号,并可以设置临时文件的存放目录和HTTP Proxy。 如果你想自定义代码模板,可以参考该插件提供的自定义代码模板文档(https://github.com/shuzijun/leetcode-editor/blob/master/doc/CustomCode.md)。通过这个插件,你可以方便地在IDEA中刷leetcode,并享受更好的调试体验。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [好用的idea插件leetcode editor【详细安装指南】](https://blog.csdn.net/weixin_45988401/article/details/129170239)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [IDEA插件系列(112):LeetCode Editor插件——LeetCode编辑器](https://blog.csdn.net/cnds123321/article/details/119859448)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值