您的位置:首页 > 娱乐 > 八卦 > Day34 | 322. 零钱兑换 279.完全平方数 139.单词拆分

Day34 | 322. 零钱兑换 279.完全平方数 139.单词拆分

2024/10/6 18:23:00 来源:https://blog.csdn.net/q864508127/article/details/141057128  浏览:    关键词:Day34 | 322. 零钱兑换 279.完全平方数 139.单词拆分

语言

Java

322. 零钱兑换  

零钱兑换  

题目

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

计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。

你可以认为每种硬币的数量是无限的。

思路

跟前几天的题很类似,不过本题求的是最小方法。

采用动规五部曲进行分析。

1.确定dp数组以及下标的含义

为j时达到amount的最小硬币个数

2.确定递推公式

dp[j] = min(dp[j - coins[i]] + 1, dp[j]);

凑够总额为j - coin[i]最少个数为dp[j - coins[i]],那么只需要加上一个钱币coins[i]即dp[j - coins[i]] + 1就是dp[j](考虑coins[i])

所以dp[j] 要取所有 dp[j - coins[i]] + 1 中最小的。

3.初始化:

 dp[0] = 0;

4.遍历顺序:

因为本题是求最少硬币个数,不涉及组合和排列,所以顺序不影响。

5.举例推导是否正确

代码

class Solution {public int coinChange(int[] coins, int amount) {int max = Integer.MAX_VALUE;int[] dp = new int[amount + 1];//定义dp数组要最少的硬币数for (int i = 0; i < dp.length; i++) {dp[i] = max;}dp[0] = 0;for (int i = 0; i < coins.length; i++) {for (int j = coins[i];j <= amount; j++) {if (dp[j - coins[i]] != max) {dp[j] = Math.min(dp[j], dp[j - coins[i]] + 1);}}}return dp[amount] == max ? -1 : dp[amount];}
}

易错点

弄懂递推公式。

先遍历dp数组给赋给最大值。

返回的时候判读是最大值就返回-1,否则正常返回。

279.完全平方数

完全平方数

题目

给你一个整数 n ,返回 和为 n 的完全平方数的最少数量 。

完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,149 和 16 都是完全平方数,而 3 和 11 不是。

思路

采用动规五部曲进行分析。

1.确定dp数组以及下标的含义

为j时完全平方数的最少数量

2.确定递推公式

dp[j] 可以由dp[j - i * i]推出, dp[j - i * i] + 1 便可以凑成dp[j]。

此时我们要选择最小的dp[j],所以递推公式:dp[j] = min(dp[j - i * i] + 1, dp[j]);

3.初始化:

 dp[0] = 0;

4.遍历顺序:

因为本题是求完全平方数的最少数量,不涉及组合和排列,所以顺序不影响。

5.举例推导是否正确

代码

class Solution {public int numSquares(int n) {int max = Integer.MAX_VALUE;int[] dp = new  int[n + 1];for (int i = 0; i <= n; i++) {dp[i] = max;} dp[0] = 0;for (int i = 1; i * i <= n; i++) {for (int j = i * i; j <= n; j++) {dp[j] = Math.min(dp[j - i * i] + 1, dp[j]);}}return dp[n];}
}

易错点

递推公式比较难想,跟前几题的类似,搞懂了前几题这个就搞懂了。

139.单词拆分

单词拆分

题目

给你一个字符串 s 和一个字符串列表 wordDict 作为字典。如果可以利用字典中出现的一个或多个单词拼接出 s 则返回 true。

注意:不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。

思路

采用动规五部曲进行分析。

1.确定dp数组以及下标的含义

dp[i]为true代表出现过一个或多个单词

2.确定递推公式

如果确定dp[j] 是true,且 [j, i] 这个区间的子串出现在字典里,那么dp[i]一定是true。(j < i )。

所以递推公式是 if([j, i] 这个区间的子串出现在字典里 && dp[j]是true) 那么 dp[i] = true。

3.初始化:

 dp[0] = true;

4.遍历顺序:

先遍历 背包,再遍历物品

5.举例推导是否正确

代码

class Solution {public boolean wordBreak(String s, List<String> wordDict) {boolean[] dp = new boolean[s.length() + 1];dp[0] = true;for (int i = 1; i <= s.length(); i++) {for (String word : wordDict) {int len = word.length();if (i >= len && dp[i - len] && word.equals(s.substring(i - len, i))) {dp[i] = true;break;}}}return dp[s.length()];}
}

易错点

递推公式需要三个条件都满足。

总结

二刷的时候好好理解以下这几道题的递推公式。

继续努力!

不经一翻彻骨寒,怎得梅花扑鼻香

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com