dp 类找零钱类问题

作者: Tim在路上 | 来源:发表于2020-05-14 17:07 被阅读0次

这类问题,需要维护,之前的状态,当前的状态是 (当前 - 当前值) 的上一个状态的最值相关

零钱兑换

给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。

示例 1:

输入: coins = [1, 2, 5], amount = 11
输出: 3
解释: 11 = 5 + 5 + 1
示例 2:

输入: coins = [2], amount = 3
输出: -1

  // 贪心思想,零钱兑换, 和平方求和的题目类似
    public int coinChange(int[] coins, int amount) {
        if(coins == null || coins.length == 0){
            return -1;
        }
        Arrays.sort(coins);
        int[] dp = new int[amount+1];
        for (int i=1;i<amount+1;i++){
            int min = amount +1;
            for (int j=0;j<coins.length;j++){
                    if (coins[j] > i){
                        break;
                    }
                    // 只需要处理当前值得状态,不需要管怎么计算
                    min = Math.min(min,dp[i-coins[j]] + 1);
            }
            dp[i] = min;
        }
        if (dp[amount] == amount+1){
            return -1;
        }
        return dp[amount];
    }

279 完全平方数

给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, ...)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。

示例 1:

输入: n = 12 输出: 3 解释: 12 = 4 + 4 + 4.

public int numSquares(int n) {
        int sqareLen = (int)(Math.sqrt(n));
        int[] numSqare = new int[sqareLen];
        for(int i=1;i<=sqareLen;i++){
            numSqare[i-1] = i * i;
        }
        int[] dp = new int[n+1];
        dp[0] = 0;
        dp[1] = 1;
        for(int i=2;i<=n;i++){
            int count = n+1;
            for(int j=0;j < sqareLen && numSqare[j]<= i;j++){
                count = Math.min(count,dp[i-numSqare[j]]+1);
            }
            dp[i] = count;
        }
        return dp[n];
    }
  1. 分割等和子集

给定一个只包含正整数的非空数组。是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。

注意:

每个数组中的元素不会超过 100
数组的大小不会超过 200
示例 1:

输入: [1, 5, 11, 5]

输出: true

解释: 数组可以分割成 [1, 5, 5] 和 [11].

示例 2:

输入: [1, 2, 3, 5]

输出: false

解释: 数组不能分割成两个元素和相等的子集.

 public boolean canPartition(int[] nums) {
        if(nums == null || nums.length == 0){
            return false;
        }
        int sum = 0;
        for(int x:nums){
            sum += x;
        }
        if(sum % 2 == 1){
            return false;
        }
        // 使用背包问题的动态规划进行求解
        boolean[][] dp = new boolean[nums.length][sum/2+1];
        int target = sum/2;
        if(nums[0] <= target){
            dp[0][nums[0]] = true;
        }

        for(int i=1;i<nums.length;i++){
            for(int j=0;j<=target;j++){
                dp[i][j] = dp[i-1][j];
                if(nums[i]<=j){
                    dp[i][j] = dp[i-1][j] || dp[i-1][j-nums[i]];
                }
            }
            if(dp[i][target]){
                return true;
            }
        }
        return dp[nums.length-1][target];
    }

相关文章

  • dp 类找零钱类问题

    这类问题,需要维护,之前的状态,当前的状态是 (当前 - 当前值) 的上一个状态的最值相关 零钱兑换 给定不同面额...

  • 背包问题详解

    目录 问题引入 在介绍背包问题之前,我们先来看一个小问题:找零钱问题。 找零钱问题 背包问题的一个浅显版本是找零钱...

  • 10.28 - 九章高级算法班题目大总结(5,6课)

    课程5: dp问题1,滚动数组优化,博弈类,记忆化搜索 Longest Increasing Continuous...

  • 记一类DP问题-【动首动脚】右上三角DP 2020-09-05(

    这里不再剖析如何理清和理解DP问题的思路,而是仅仅记录同一类DP问题,希望从更细小的角度对这类特定问题形成更深刻的...

  • 状压DP——二进制的妙用

    之前我们讲解了背包问题、树形DP,区间DP这三类问题。这些都是中规中矩的动态规划题目。今天,我为大家讲解一种比较有...

  • 区间类DP总结

    区间类DP的做法,是用memorized search,把大区间拆分为小区间来解。而dp[i][j] 则直观的表示...

  • 算法思想之动态规划(三)——找零钱问题

    前言 今天我们继续讨论经典的动态规划问题之找零钱问题。 找零钱问题 问题描述 假设你是一名超市收银员,现有种不同面...

  • [LeetCode]动态规划问题--股票买卖最佳时机

    LeetCode中很重要的一类算法是动态规划(DP:dynamic programming),典型的有背包问题、股...

  • DP问题求解(一)爬楼梯

    DP问题求解之爬楼梯 DP算法是在面试或者机试中会重点考察的一类问题,而且这类问题一般难度比较大,所以想花一点时间...

  • 找零钱问题

    问题 这个题目要求编写一段程序实现统一银座超市的找零方案。只需输入要补给顾客的 金额,然后通过程序就可以计算出该金...

网友评论

    本文标题:dp 类找零钱类问题

    本文链接:https://www.haomeiwen.com/subject/knfxohtx.html