LeetCode check-in day46-- word splitting and multiple knapsack problems


knowledge summary

I wrote a topic today, but it is quite difficult, and it is a high-frequency interview topic

Also went over the multiple knapsack problem.

The difference between multiple knapsacks and 01 knapsacks is that multiple knapsacks limit the number of items, and the number of some items may not be 1, and can be used twice or more times. The problem can actually be transformed into 01 knapsack. The code reference is as follows and the time
is
complicated Degree O(m * n * k)

public void testMultiPack1(){
    
    
    // 版本一:改变物品数量为01背包格式
    List<Integer> weight = new ArrayList<>(Arrays.asList(1, 3, 4));
    List<Integer> value = new ArrayList<>(Arrays.asList(15, 20, 30));
    List<Integer> nums = new ArrayList<>(Arrays.asList(2, 3, 2));
    int bagWeight = 10;

    for (int i = 0; i < nums.size(); i++) {
    
    
        while (nums.get(i) > 1) {
    
     // 把物品展开为i
            weight.add(weight.get(i));
            value.add(value.get(i));
            nums.set(i, nums.get(i) - 1);
        }
    }

    int[] dp = new int[bagWeight + 1];
    for(int i = 0; i < weight.size(); i++) {
    
     // 遍历物品
        for(int j = bagWeight; j >= weight.get(i); j--) {
    
     // 遍历背包容量
            dp[j] = Math.max(dp[j], dp[j - weight.get(i)] + value.get(i));
        }
        System.out.println(Arrays.toString(dp));
    }
}

public void testMultiPack2(){
    
    
    // 版本二:改变遍历个数
    int[] weight = new int[] {
    
    1, 3, 4};
    int[] value = new int[] {
    
    15, 20, 30};
    int[] nums = new int[] {
    
    2, 3, 2};
    int bagWeight = 10;

    int[] dp = new int[bagWeight + 1];
    for(int i = 0; i < weight.length; i++) {
    
     // 遍历物品
        for(int j = bagWeight; j >= weight[i]; j--) {
    
     // 遍历背包容量
            // 以上为01背包,然后加一个遍历个数
            for (int k = 1; k <= nums[i] && (j - k * weight[i]) >= 0; k++) {
    
     // 遍历个数
                dp[j] = Math.max(dp[j], dp[j - k * weight[i]] + k * value[i]);
            }
            System.out.println(Arrays.toString(dp));
        }
    }
}


Leetcode 139. Word Splitting

topic link

topic description

Given a string s and a list of strings wordDict as a dictionary. Please judge whether s can be spliced ​​out of words that appear in the dictionary.

Note: It is not required to use all the words in the dictionary, and the words in the dictionary can be used repeatedly.
insert image description here

code description

The point is to find the recursive formula and how to traverse items.

Firstly, the problem is transformed into a complete knapsack problem, the item is each word, and it is asked whether the knapsack can be filled with items.

The recursive formula is
If dp[j] can be composed of words, and the substring of the string [j, i] belongs to worddic, then dp[i] can also be composed of words

dp[i] = dp[j] && worddict.contains(s.substring(j, i))

Traversal order:
backpack first, then items: number of permutations
Items first, then backpack: number of combinations

Because applepenapple != penappleapple, so this question needs to use the number of permutations, and the traversal order is the backpack capacity first and then the items

The time complexity is O(N^3), because the complexity of the substring method is O(n)

class Solution {
    
    
    public boolean wordBreak(String s, List<String> wordDict) {
    
    
        boolean[] dp = new boolean[s.length() + 1];
        HashSet<String> set = new HashSet<>(wordDict);
        dp[0] = true;
        // 求排列数, 所有先遍历背包容量, 再遍历物品
        for(int i = 0; i <=s.length(); i++){
    
    
            for(int j = 0; j < i; j++){
    
    
                if(dp[j] && set.contains(s.substring(j, i))){
    
    
                    dp[i] = true;
                }
            }        
            // System.out.println(Arrays.toString(dp));
        }
        return dp[s.length()];
    }
}

// 另一种思路的背包算法
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()];
    }
}

Guess you like

Origin blog.csdn.net/weixin_45872648/article/details/131444975