LeeCode check-in day42,43 --01 backpack problem and its application


knowledge summary

Learn the knapsack problem and its application today, focusing on mastering its ideas and how to compare other problems with the knapsack problem


Leetcode Knapsack Problem

topic description

The classic knapsack, given the capacity and value of the specified item, find the maximum value of the item that can be loaded under the specified knapsack capacity.

code description

Some routines to remember:

  1. The two-dimensional array represents the current item i, the maximum value that can be loaded under the knapsack capacity j.
  2. One-dimensional array refers to a scrolling array, the traversal order is fixed, the items are traversed first, and then the capacity is traversed, and it needs to be traversed in reverse order.
  3. Recursion formula:

dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i])

package com.backpack;
import org.junit.jupiter.api.Test;
import java.util.Arrays;

public class backpack {
    
    
    int[] weight = {
    
    1, 3, 4, 2};
    int[] value = {
    
    15, 27, 30, 20};
    int bagSize = 5;



    @Test
    void test2Dbackpack() {
    
    
        int num = weight.length;
        int[][] dp = new int[num][bagSize + 1];
        // initialize the first row
        for (int j = 0; j <= bagSize; j++) {
    
    
            // when the first item weight is larger or equal than
            // the current bag size, we can put the item into the bag
            if (weight[0] <= j) dp[0][j] = value[0];
        }

        for (int i = 1; i < num; i++) {
    
     //遍历物品
            for (int j = 1; j <= bagSize; j++) {
    
     // 遍历背包
                if (j - weight[i] < 0) {
    
    
                    dp[i][j] = dp[i - 1][j]; // 当前容量不能放得下物品i
                } else {
    
    
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
                }
            }
        }
        for (int i = 0; i < num; i++) {
    
    
            System.out.println(Arrays.toString(dp[i]));
        }

        System.out.println("Max value is " + dp[num - 1][bagSize]);
    }

    @Test
    void test1Dbackpack() {
    
    
        int[] dp = new int[bagSize + 1];
        dp[0] = 0;
        for (int i = 0; i < weight.length; i++) {
    
    
            for (int j = bagSize; j >= 0; j--) {
    
    
                if (j >= weight[i]) {
    
    
                    dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i]);
                }
            }
            System.out.println(Arrays.toString(dp));
        }
        System.out.println("Max value is " + dp[bagSize]);
    }
}


Leetcode 416. Split Equal Sum Subsets

topic link

topic description

You are given a non-empty array nums containing only positive integers. Please judge whether this array can be divided into two subsets so that the sum of the elements of the two subsets is equal.

insert image description here

code description

Transform the problem into: Can a backpack with a capacity of sum/2 be filled with items worth sum/2? If so, it can be equally divided, otherwise it cannot. The volume and value of the items
here are equal

class Solution {
    
    
    public boolean canPartition(int[] nums) {
    
    
        int sum = 0;
        for(int i = 0; i < nums.length; i++){
    
    
            sum += nums[i];
        }
        if(sum % 2 == 1) return false;
        int target = sum / 2;
        int[] dp = new int[target+1];
        dp[0] = 0;
        for(int i = 0; i < nums.length; i++){
    
    
            for(int j = target; j >= nums[i]; j--){
    
    
                dp[j] = Math.max(dp[j], dp[j - nums[i]] + nums[i]);   
            }
            // System.out.println(Arrays.toString(dp));
        }
        return dp[target] == target;
    }
}

Leetcode 1049. The Weight of the Last Stone II

topic link

topic description

There is a pile of stones represented by an integer array stones. Where stones[i] represents the weight of the i-th stone.

Each turn, choose any two stones from among them, and smash them together. Suppose the weights of stones are x and y respectively, and x <= y. Then the possible outcomes of crushing are as follows:

If x == y, then both stones will be completely shattered;
if x != y, then the stone with weight x will be completely shattered, and the stone with weight y will have a new weight of yx.
In the end, at most one stone will remain. Returns the smallest possible weight for this stone. Returns 0 if no stones are left.

insert image description here

code description

This question will be similar to the previous question. If it can be divided equally, then it will return 0, but if it cannot be divided equally, what should I do?

Divide the stones into two groups, and the difference between the two groups should be as small as possible. Assuming the total is 23, then target = 11, and the other side is 12. The maximum value that can be loaded in a backpack with a capacity of 11 is: dp [target] <= 11, then the value difference between the two backpacks = (sum - dp[target]) - dp[target]

class Solution {
    
    
    public int lastStoneWeightII(int[] stones) {
    
    
        int sum = 0;
        for(int i = 0; i < stones.length; i ++){
    
    
            sum += stones[i];
        }
        int target = sum / 2;
        int[] dp = new int[target+1];
        for(int i = 0; i < stones.length; i++){
    
    
            for(int j = target; j >= stones[i]; j--){
    
    
                dp[j] = Math.max(dp[j], dp[j - stones[i]] + stones[i]);
            }
            //  System.out.println(Arrays.toString(dp));
        }
        return sum  - 2 * dp[target];
    }
}

Leetcode 494. Goal and

topic link

topic description

You are given an integer array nums and an integer target.

Add '+' or '-' to each integer in the array, and then concatenate all the integers to construct an expression:

For example, nums = [2, 1], you can add '+' before 2, add '-' before 1, and then concatenate to get the expression "+2-1".
Returns the number of distinct expressions that can be constructed by the above methods that evaluate to target.

insert image description here

code description

Here is a very clever transformation, target can be regarded as a positive - negative group,
positive + negative = sum, all positive = (sum + target) / 2
problems are transformed into how many ways to fill a backpack with a capacity of positive.

It should be noted that if the target is a negative number, it needs to be converted into a positive number for operation.

class Solution {
    
    
    public int findTargetSumWays(int[] nums, int target) {
    
    

        int sum = 0;
        for(int num : nums){
    
    
            sum += num;
        }
        if(target < 0) target = -target;

        int total = sum += target;
        if(total % 2 != 0) return 0;
        int bagSize = Math.abs(total / 2);

        int[] dp = new int[bagSize+1];
        dp[0] = 1;

        for(int i = 0; i < nums.length; i++){
    
    
            for(int j = bagSize; j>= nums[i]; j--){
    
    
                dp[j] += dp[j - nums[i]];
            }
            // System.out.println(Arrays.toString(dp));
        }
        return dp[bagSize];
    }
}

Leetcode 474. Ones and Zeros

topic link

topic description

You are given an array of binary strings strs and two integers m and n.

Please find out and return the length of the largest subset of strs, in which there are at most m 0s and n 1s.

A set x is a subset of a set y if all elements of x are also elements of y.

code description

class Solution {
    
    
    public int findMaxForm(String[] strs, int m, int n) {
    
    
        int[][] dp = new int[m+1][n+1];
        for(String str : strs){
    
    
            int x = 0, y = 0;
            for(char ch : str.toCharArray()){
    
    
                if(ch == '0'){
    
    
                    x++;
                }else{
    
    
                    y++;
                }
            }

            for(int i = m; i >= x; i--){
    
    
                for(int j = n; j >= y; j--){
    
    
                    dp[i][j] = Math.max(dp[i][j], dp[i-x][j-y] + 1);
                }
            }
        }

        return dp[m][n];
    }
}

Guess you like

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