递归和动态规划——整数和
给你一个数组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]; }