数据结构与算法(Java) 54:数值累加

题目 给你一个数组arr,和一个整数aim。如果可以任意选择arr中的数字,能不能累加得到aim,返回true或者false。

思路 【暴力递归】类似于子序列问题,遍历数组,当前数值可以选择要它,或者不要它。

【动态规划】设计一张二维dp表,行代表arr中的每一个数的位置,共arr.length + 1行(包含了越界位);若数组中全部元素的加和为sum,那么列代表范围是0~sum的加和。根据basecase可以看出,当sum=aim时,返回true,所以dp中最后一行(越界位)dp[arr.length][aim] = true,同一行的其他位置为false.根据最后一行的信息,从下往上每一行开始计算。根据暴力递归的步骤可以看出,dp[arr.lenght - 1][0]位置依赖于dp[arr.lenght][0]和dp[arr.lenght][0+arr[arr.lenght - 1]],其他同理,注意边界的条件。

package algorithm.section8;

public class Sum {
    public static boolean isSum1(int[] arr, int i, int sum, int aim) {
        if (i == arr.length) return sum == aim;

        return isSum1(arr, i + 1, sum, aim) || isSum1(arr, i + 1, sum + arr[i], aim);
    }

    public static boolean isSum2(int[] arr, int aim) {
        int sum = 0;
        for (int value : arr) sum += value;

        if (sum < aim) return false;

        boolean[][] dp = new boolean[arr.length + 1][sum + 1];
        dp[arr.length][aim] = true;

        for (int i = dp.length - 2; i >= 0; i--)
            for (int j = 0; j < dp[0].length; j++) {
                if (dp[i + 1][j]) dp[i][j] = true;
                if (j + arr[i] < dp[0].length)
                    dp[i][j] = (dp[i + 1][j] || dp[i + 1][j + arr[i]]);
            }

        return dp[0][0];
    }

    public static void main(String[] args){
        int[] arr = {2, 3, 5};
        int aim = 7;
        System.out.println(isSum1(arr, 0, 0, aim));
        System.out.println(isSum2(arr, aim));
    }
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值