• 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 的不同 表达式 的数目。

    1. 输入:nums = [1,1,1,1,1], target = 3
    2. 输出:5
    3. 解释:一共有 5 种方法让最终目标和为 3
    4. -1 + 1 + 1 + 1 + 1 = 3
    5. +1 - 1 + 1 + 1 + 1 = 3
    6. +1 + 1 - 1 + 1 + 1 = 3
    7. +1 + 1 + 1 - 1 + 1 = 3
    8. +1 + 1 + 1 + 1 - 1 = 3
    1. import java.util.Scanner;
    2. /**
    3. * @author light
    4. * @Description 目标和
    5. *
    6. *(思路:可以将数组分为两部分left和right,
    7. * 即有left-right=target;
    8. * 又有left+right=sum;
    9. * 转化为left=(sum+target)/2
    10. * 所以有两个解法---1.回溯求目标和;2.转化维持01背包问题---背包容量为left;
    11. * @create 2023-09-26 10:13
    12. */
    13. public class FindTargetSumWaysTest {
    14. public static void main(String[] args) {
    15. Scanner input=new Scanner(System.in);
    16. int n= input.nextInt();
    17. int[] nums=new int[n];
    18. for (int i = 0; i < n; i++) {
    19. nums[i]=input.nextInt();
    20. }
    21. int target=input.nextInt();
    22. System.out.println(findTargetSumWays(nums, target));
    23. }
    24. public static int findTargetSumWays(int[] nums, int target) {
    25. int sum=0;
    26. for (int num : nums) {
    27. sum+=num;
    28. }
    29. if(Math.abs(target)>sum){
    30. return 0; //找不到组合
    31. }
    32. int left=(sum+target)/2;
    33. if((sum+target)%2!=0){
    34. return 0; //找不到组合
    35. }
    36. //动规
    37. //dp[j]:装满容量为j的背包共有dp[j]种方法
    38. int[] dp=new int[left+1];
    39. dp[0]=1;
    40. for (int i = 0; i < nums.length; i++) { //先遍历物品
    41. for(int j=left;j>=nums[i];j--){ //再遍历背包
    42. dp[j]+=dp[j-nums[i]];
    43. }
    44. }
    45. return dp[left];
    46. }
    47. }

    474. 一和零 - 力扣(LeetCode)

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

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

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

    1. 输入:strs = ["10", "0001", "111001", "1", "0"], m = 5, n = 3
    2. 输出:4
    3. 解释:最多有 5031 的最大子集是 {"10","0001","1","0"} ,因此答案是 4
    4. 其他满足题意但较小的子集包括 {"0001","1"} 和 {"10","1","0"} 。{"111001"} 不满足题意,因为它含 41 ,大于 n 的值 3
    1. import java.util.Scanner;
    2. /**
    3. * @author light
    4. * @Description 一和零
    5. * 给你一个二进制字符串数组 strs 和两个整数 m 和 n 。
    6. *
    7. * 请你找出并返回 strs 的最大子集的长度,该子集中 最多 有 m 个 0 和 n 个 1 。
    8. *
    9. * 如果 x 的所有元素也是 y 的元素,集合 x 是集合 y 的 子集 。
    10. *
    11. * (思路:转化为01背包问题
    12. * @create 2023-09-26 10:58
    13. */
    14. public class FindMaxFormTest {
    15. public static void main(String[] args) {
    16. Scanner input=new Scanner(System.in);
    17. String[] strs=input.next().split(",");
    18. int m=input.nextInt();
    19. int n=input.nextInt();
    20. System.out.println(findMaxForm(strs, m, n));
    21. }
    22. public static int findMaxForm(String[] strs, int m, int n) {
    23. //dp[i][j]:最多有i个0,j个1的str的最大子集长度为dp[i][j]
    24. int[][] dp=new int[m+1][n+1];
    25. int zeroNum;
    26. int oneNum;
    27. dp[0][0]=0;
    28. //遍历物品
    29. for (String str : strs) {
    30. zeroNum=0;
    31. oneNum=0;
    32. for (int i = 0; i
    33. char ch=str.charAt(i);
    34. if(ch=='0'){
    35. zeroNum++;
    36. }else {
    37. oneNum++;
    38. }
    39. }
    40. //倒叙遍历---遍历背包
    41. for (int i =m; i >=zeroNum ; i--) {
    42. for (int j = n; j >=oneNum; j--) {
    43. dp[i][j]=Math.max(dp[i][j],dp[i-zeroNum][j-oneNum]+1);
    44. }
    45. }
    46. }
    47. return dp[m][n];
    48. }
    49. }

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

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

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

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

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

    1. 输入:amount = 5, coins = [1, 2, 5]
    2. 输出:4
    3. 解释:有四种方式可以凑成总金额:
    4. 5=5
    5. 5=2+2+1
    6. 5=2+1+1+1
    7. 5=1+1+1+1+1
    1. /**
    2. * @author light
    3. * @Description 零钱兑换II
    4. *
    5. * (思路:转化为完全背包问题
    6. * @create 2023-09-26 11:45
    7. */
    8. public class ChangeTest {
    9. public int change(int amount, int[] coins) {
    10. //dp[j]:凑成总金额为j的硬币组合数为dp[j]
    11. int[] dp=new int[amount+1];
    12. dp[0]=1;
    13. for (int i = 0; i < coins.length; i++) {
    14. for (int j = coins[i]; j <=amount; j++) {
    15. dp[j]+=dp[j-coins[i]];
    16. }
    17. }
    18. return dp[amount];
    19. }
    20. }

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

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

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

    1. 输入:nums = [1,2,3], target = 4
    2. 输出:7
    3. 解释:
    4. 所有可能的组合为:
    5. (1, 1, 1, 1)
    6. (1, 1, 2)
    7. (1, 2, 1)
    8. (1, 3)
    9. (2, 1, 1)
    10. (2, 2)
    11. (3, 1)
    12. 请注意,顺序不同的序列被视作不同的组合。
    1. /**
    2. * @author light
    3. * @Description 组合总和IV
    4. * 请注意,顺序不同的序列被视作不同的组合。---相当于求排列
    5. * (思路:转化为完全背包问题,对于排列问题,先遍历背包,在遍历物品
    6. * @create 2023-09-26 12:23
    7. */
    8. public class CombinationSum4Test {
    9. public int combinationSum4(int[] nums, int target) {
    10. //dp[j]:总和为j的背包的元素排列个数为dp[j]
    11. int[] dp=new int[target+1];
    12. dp[0]=1;
    13. for (int i = 0; i <=target ; i++) { //先背包
    14. for (int j = 0; j < nums.length; j++) { //在物品
    15. if(i>=nums[j]){
    16. dp[i]+=dp[i-nums[j]];
    17. }
    18. }
    19. }
    20. return dp[target];
    21. }
    22. }

    70. 爬楼梯 - 力扣(LeetCode)

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

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

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

    1. 输入:n = 2
    2. 输出:2
    3. 解释:有两种方法可以爬到楼顶。
    4. 1. 1 阶 + 1
    5. 2. 2
    1. /**
    2. * @author light
    3. * @Description 爬楼梯进阶版
    4. *
    5. * (思路:
    6. * 1阶,2阶,.... m阶就是物品,楼顶就是背包。
    7. *
    8. * 每一阶可以重复使用,例如跳了1阶,还可以继续跳1阶。
    9. *
    10. * 问跳到楼顶有几种方法其实就是问装满背包有几种方法。
    11. *
    12. *这就是一个完全背包问题了
    13. * @create 2023-09-26 14:54
    14. */
    15. public class ClimbStairsProTest {
    16. public int climbStairs(int n,int m) {
    17. //dp[i]:爬到第i阶楼梯共有dp[i]种方法
    18. int[] dp=new int[n+1];
    19. dp[0]=1;
    20. for (int i = 1; i <=n ; i++) { //先背包
    21. for (int j = 1; j <=m; j++) { //再物品
    22. if(i>=j){
    23. dp[i]+=dp[i-j];
    24. }
    25. }
    26. }
    27. return dp[n];
    28. }
    29. }

  • 相关阅读:
    鸿蒙 navigation路由跳转,页面struct 下的生命周期、onShow、onHidden等不会触发问题
    如何在Docker容器中运行和使用dnsmasq?
    hutool、esayPoi、easyExcel、读写数据,性能对比
    linux驱动之休眠与唤醒
    Docker中MySql容器的数据挂载
    2022年最新山东交安安全员模拟真题及答案
    关于:获取当前客户端登录的域控
    skdaima
    spring的bean初始化策略
    这家公司因Log4j漏洞惨遭黑客攻击并勒索500万美元
  • 原文地址:https://blog.csdn.net/zssxcj/article/details/133297968