动态规划-将数组分成两个数组,并最小化数组和的差(java)

265 篇文章 2 订阅
235 篇文章 0 订阅
文章介绍了如何将一个正数数组分成两个子数组,使得两数组之和的差值最小。提供了暴力递归的解题思路和代码实现,以及使用动态规划优化后的代码实现,强调了动态规划在解决此类问题中的应用,并给出了相关动态规划题目链接。
摘要由CSDN通过智能技术生成

将数组分成两个数组,并最小化数组和的差

给定一个正数数组arr, 请把arr中所有的数分成两个集合,
尽量让两个集合的累加和接近 返回最接近的情况下,较小集合的累加和

暴力递归

解题思路

我们先求出数组的累加和sum.然后拆分数组时,让较小集合去逼近
sum/2.这样得出的数组就是符合要求的.
递归思路:
每到一个数,有选择和不选两种情况,分开讨论,返回最逼近sum/2 的最大值.

代码演示

 /**
     * 暴力递归求拆分数组
     * @param arr
     * @return
     */
    public static int right(int[] arr) {
        if (arr == null || arr.length < 2){
            return 0;
        }
        int sum  = 0;
        for (int a : arr){
            sum += a;
        }

        return process(arr,0,sum / 2);
    }

    /**
     * 递归分割数组
     * 思路:arr[i...]
     * 可以自由选择,请返回累加和尽量接近sum,但不能超过sum的情况下,最接近的累加和是多少
     * @param arr 数组
     * @param index 下标
     * @param sum 需要达成的目标
     * @return
     */
    public static int process(int[]arr,int index,int sum){
        if (index == arr.length){
            return 0;
        }
        //不选当前数字的情况
        int p1 = process(arr,index + 1,sum);

        //选择当前数字的情况
        int p2 = 0;
        //当前数字 不能比剩余要选择的数字还大.
        if (arr[index] <= sum){
            //选择index 位置后,剩下需要去完成的任务还剩sum-arr[index]
            p2 = arr[index] + process(arr,index+1,sum-arr[index]);
        }

        //选择接近sum / 2 的最大值,这样两个数组和最接近
        return Math.max(p1,p2);
    }

动态规划

动态规划就是对递归的改写,还是三个步骤.
1.根据base case 初始化dp表
2.递归过程改成从表中拿数据的过程
3.返回递归调用的最初始状态

代码演示

 /**
     * 动态规划
     * @param arr
     * @return
     */
    public static int dp(int[]arr){
        if (arr == null || arr.length < 2){
            return 0;
        }
        int sum  = 0;
        for (int a : arr){
            sum += a;
        }

        int binarySum = sum / 2;
        int N = arr.length;
        //动态规划表
        //base case 里 index == N 值为0.java 表初始化本身就是0.不需要在初始化了
        int[][]dp = new int[N + 1][binarySum + 1];
        //递归过程改成表中拿数据
        for (int i = N - 1;i >= 0 ;i--){
            for (int j = 0;j <= binarySum;j++){

                int p1 = dp[i + 1][j];

                //选择当前数字的情况
                int p2 = 0;
                //当前数字 不能比剩余要选择的数字还大.
                if (arr[i] <= j){
                    p2 = arr[i] + dp[i + 1][j - arr[i]];
                }
               dp[i][j] =  Math.max(p1,p2);

            }
        }
        //返回递归的最初始状态
        return dp[0][binarySum];
    }

动态规划专题

leetcode337. 打家劫舍 III

整数拆分问题

leetcode213. 打家劫舍 II

leetcode198. 打家劫舍

leetcode174. 地下城游戏

打败怪兽的概率

leetcode688. 骑士在棋盘上的概率

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值