平均拆分数组

问题一:给一个数组,输出这个数组拆分为两个数组,使得两个数组的差值最小

//注意target就是数组总和的一半:sum/2
//dp[i][j]表示从数组的[0,i]下标范围内选取若干个正整数,达到总和为j的最小总和
public static int func(int[] nums){
		int sum = 0;
        for(int i:nums) sum+=i;
        int target = sum/2;
        
        int[][] dp = new int[nums.length+1][target+1];
        for (int i=1;i<=nums.length;i++){
            for (int j=1;j<=target;j++){
                if (j>=nums[i-1]){//如果大于 就可以进行二选一
                    dp[i][j] = Math.max(dp[i-1][j],dp[i-1][j-nums[i-1]]+nums[i-1]);
                }else{
                    dp[i][j] = dp[i-1][j];
                }
            }
        }
        return dp[nums.length][target];
    }

问题二:给一个数组,是否可以等值分割成两个子集,使得两个子集的元素和相等。

public static boolean func2(int[] nums) {
        int n = nums.length;
        int sum = 0;
        for(int i:nums) sum+=i;
        int target = sum/2;
        
        boolean[][] dp = new boolean[n + 1][target + 1];
        // 如果不选取任何正整数,则被选取的正整数等于 0。因此对于所有 0≤i<n,都有 dp[i][0]=true
        for (int i = 0; i <= n; i++) {
            dp[i][0] = true;
        }

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

问题三:将一个数组拆分为两个数组使得两个数组的差值最小,求出对应的两个数组

package huatielu;/*
@author Oblak
@date 2022/4/14
@description 可以求得:将一个数组拆分为两个数组使得两个数组的差值最小
求出对应的两个数组
*/

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

public class bag01 {
    public static void main(String[] args) {
        int[] nums = new int[]{1,3,5,7,5,2,5};
        int sum = 0;
        HashMap<Integer,Integer> map= new HashMap<>();
        for (int i:nums){
            sum+=i;
            map.put(i,map.getOrDefault(i,0)+1);
        }
        int ans = func(nums, sum / 2);

        boolean[][] booleans = func2(nums, ans);
        List<Integer> list = new ArrayList<>();
        int target = ans;

        //寻找路径 从原来的boolean中先找target位置是否有满足的条件,有的话加入list,然后更新target
        int n = nums.length;
        while (target>0){
            for (int i=1;i<=n;i++){
                if (booleans[i][target]){
                    list.add(nums[i-1]);
                    //System.out.println(nums[i-1]);
                    target-=nums[i-1];
                    n=i-1;//之后的n只能从前面的糖果袋中取
                    break;
                }
            }
        }

        for (int i=0;i<list.size();i++){
            if (i==0) System.out.print(list.get(0));
            else System.out.print(" "+list.get(i));
            map.put(list.get(i),map.get(list.get(i))-1);
        }
        System.out.println();

        List<Integer> list2 = new ArrayList<>();
        for (int i=0;i<nums.length;i++){
            if (map.get(nums[i])>0){
                list2.add(nums[i]);
                map.put(nums[i],map.get(nums[i])-1);
            }
        }

        for (int i=0;i<list2.size();i++){
            if (i==0) System.out.print(list2.get(0));
            else System.out.print(" "+list2.get(i));
        }

    }

    public static int func(int[] nums,int target){
        int[][] dp = new int[nums.length+1][target+1];

        for (int i=1;i<=nums.length;i++){
            for (int j=1;j<=target;j++){
                if (j>=nums[i-1]){
                    dp[i][j] = Math.max(dp[i-1][j],dp[i-1][j-nums[i-1]]+nums[i-1]);
                }else{
                    dp[i][j] = dp[i-1][j];
                }
            }

        }

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

    }

    public static boolean[][] func2(int[]nums,int target){
        int n = nums.length;
        boolean[][] dp = new boolean[n + 1][target + 1];
        // 如果不选取任何正整数,则被选取的正整数等于 0。因此对于所有 0≤i<n,都有 dp[i][0]=true
        for (int i = 0; i <= n; i++) {
            dp[i][0] = true;
        }
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= target; j++) {
                if (j - nums[i - 1] < 0) {
                    dp[i][j] = dp[i - 1][j];
                } else {
                    dp[i][j] = dp[i - 1][j] | dp[i - 1][j - nums[i - 1]];
                }
            }
        }
        for (int i=0;i<dp.length;i++){
            System.out.println(Arrays.toString(dp[i]));
        }
        return dp;
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值