背包问题更新。
This commit is contained in:
parent
dd65ec57d3
commit
c0a6bc5455
|
@ -3140,37 +3140,6 @@ private int findTargetSumWays(int[] nums, int start, int S) {
|
|||
}
|
||||
```
|
||||
|
||||
**字符串按单词列表分割**
|
||||
|
||||
[139. Word Break (Medium)](https://leetcode.com/problems/word-break/description/)
|
||||
|
||||
```html
|
||||
s = "leetcode",
|
||||
dict = ["leet", "code"].
|
||||
Return true because "leetcode" can be segmented as "leet code".
|
||||
```
|
||||
|
||||
dict 中的单词没有使用次数的限制,因此这是一个完全背包问题。
|
||||
|
||||
0-1 背包和完全背包在实现上的不同之处是,0-1 背包对物品的迭代是在最外层,而完全背包对物品的迭代是在最里层。
|
||||
|
||||
```java
|
||||
public boolean wordBreak(String s, List<String> wordDict) {
|
||||
int n = s.length();
|
||||
boolean[] dp = new boolean[n + 1];
|
||||
dp[0] = true;
|
||||
for (int i = 1; i <= n; i++) {
|
||||
for (String word : wordDict) { // 完全一个物品可以使用多次
|
||||
int len = word.length();
|
||||
if (len <= i && word.equals(s.substring(i - len, i))) {
|
||||
dp[i] = dp[i] || dp[i - len];
|
||||
}
|
||||
}
|
||||
}
|
||||
return dp[n];
|
||||
}
|
||||
```
|
||||
|
||||
**01 字符构成最多的字符串**
|
||||
|
||||
[474. Ones and Zeroes (Medium)](https://leetcode.com/problems/ones-and-zeroes/description/)
|
||||
|
@ -3229,23 +3198,83 @@ return -1.
|
|||
- 物品大小:面额
|
||||
- 物品价值:数量
|
||||
|
||||
因为硬币可以重复使用,因此这是一个完全背包问题。
|
||||
因为硬币可以重复使用,因此这是一个完全背包问题。完全背包只需要将01背包中逆序遍历bp数组改为正序遍历即可。
|
||||
|
||||
```java
|
||||
public int coinChange(int[] coins, int amount) {
|
||||
if (coins == null || coins.length == 0) {
|
||||
return 0;
|
||||
}
|
||||
int[] minimum = new int[amount + 1];
|
||||
Arrays.fill(minimum, amount + 1);
|
||||
minimum[0] = 0;
|
||||
Arrays.sort(coins);
|
||||
for (int i = 1; i <= amount; i++) {
|
||||
for (int j = 0; j < coins.length && coins[j] <= i; j++) {
|
||||
minimum[i] = Math.min(minimum[i], minimum[i - coins[j]] + 1);
|
||||
if(amount == 0) return 0;
|
||||
int[] bp = new int[amount + 1];
|
||||
for(int coin : coins){
|
||||
for(int i = coin; i <= amount; i++){ //将逆序遍历改为正序遍历
|
||||
if(i == coin)
|
||||
bp[i] = 1;
|
||||
else if(bp[i] == 0 && bp[i - coin] != 0)
|
||||
bp[i] = bp[i - coin] + 1;
|
||||
else if(bp[i - coin] != 0)
|
||||
bp[i] = Math.min(bp[i], bp[i - coin] + 1);
|
||||
}
|
||||
}
|
||||
return minimum[amount] > amount ? -1 : minimum[amount];
|
||||
return bp[amount] == 0 ? -1 : bp[amount];
|
||||
}
|
||||
```
|
||||
|
||||
**找零钱的硬币数组合**
|
||||
|
||||
[518. Coin Change 2 (Medium)](https://leetcode.com/problems/coin-change-2/description/)
|
||||
|
||||
```html
|
||||
Input: amount = 5, coins = [1, 2, 5]
|
||||
Output: 4
|
||||
Explanation: there are four ways to make up the amount:
|
||||
5=5
|
||||
5=2+2+1
|
||||
5=2+1+1+1
|
||||
5=1+1+1+1+1
|
||||
```
|
||||
|
||||
完全背包问题,使用dp记录可达成目标的组合数目。
|
||||
|
||||
```java
|
||||
public int change(int amount, int[] coins) {
|
||||
int[] dp = new int[amount + 1];
|
||||
dp[0] = 1;
|
||||
for(int coin : coins){
|
||||
for(int i = coin; i <= amount; i++){
|
||||
dp[i] += dp[i - coin];
|
||||
}
|
||||
}
|
||||
return dp[amount];
|
||||
}
|
||||
```
|
||||
|
||||
**字符串按单词列表分割**
|
||||
|
||||
[139. Word Break (Medium)](https://leetcode.com/problems/word-break/description/)
|
||||
|
||||
```html
|
||||
s = "leetcode",
|
||||
dict = ["leet", "code"].
|
||||
Return true because "leetcode" can be segmented as "leet code".
|
||||
```
|
||||
|
||||
dict 中的单词没有使用次数的限制,因此这是一个完全背包问题。该问题涉及到字典中单词的使用顺序,因此可理解为涉及顺序的完全背包问题。
|
||||
|
||||
求解该类型问题时,应调整两次循环的顺序,0-1 背包对物品的迭代是在最外层,而涉及顺序的完全背包问题对物品的迭代是在最里层。
|
||||
|
||||
```java
|
||||
public boolean wordBreak(String s, List<String> wordDict) {
|
||||
int n = s.length();
|
||||
boolean[] dp = new boolean[n + 1];
|
||||
dp[0] = true;
|
||||
for (int i = 1; i <= n; i++) {
|
||||
for (String word : wordDict) { // 完全一个物品可以使用多次
|
||||
int len = word.length();
|
||||
if (len <= i && word.equals(s.substring(i - len, i))) {
|
||||
dp[i] = dp[i] || dp[i - len];
|
||||
}
|
||||
}
|
||||
}
|
||||
return dp[n];
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -3271,7 +3300,7 @@ Note that different sequences are counted as different combinations.
|
|||
Therefore the output is 7.
|
||||
```
|
||||
|
||||
完全背包。
|
||||
涉及顺序的完全背包。
|
||||
|
||||
```java
|
||||
public int combinationSum4(int[] nums, int target) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user