递归和动态规划——整数和

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

类似于字符串的子串,数组中的每个数字都可以在求和结果中,也可以不在

所以使用递归可以求得

public static boolean isSum(int[] arr, int aim){
        if(arr.length == 0 || arr == null) return false;
        return sum(arr, aim, 0, 0);
    }
    public static boolean sum(int[] arr, int aim, int index, int res){
        if(index == arr.length){
            return aim == res;
        }
        return sum(arr, aim, index + 1, res + arr[index]) || sum(arr, aim, index + 1, res);
    }

  

改为动态规划:

* dp维度:位置index和当前的求和结果res,所以dp[arr.length + 1][aim + 1]是二维的(因为在分析可变参数时,最终的返回结果是i == arr.length,会碰到最后一行,所以长度要+1)

* 行代表数组中的第几个元素,列代表求和的结果
* 普通位置(i, j)依赖的位置有(i + 1, arr[i] + j)和(i + 1, j)

public static boolean isSum2(int[] arr, int aim){
        if(arr.length == 0 || arr == null) return false;

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

        //在最后一行其余位置上的值均不为aim,所以就是false
        for(int i = 0; i < aim; i++){
            dp[arr.length][i] = false;
        }
        //不被依赖的位置  (arr.length, aim)是true
        dp[arr.length][aim] = true;

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

  

  

原文地址:https://www.cnblogs.com/SkyeAngel/p/8967538.html