From 5a1607a02a4a8b341e9b58e6c23b21bc528a304b Mon Sep 17 00:00:00 2001 From: xiaotiancai893661742 <46739364+xiaotiancai893661742@users.noreply.github.com> Date: Wed, 10 Aug 2022 19:34:52 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8A=A8=E6=80=81=E8=A7=84=E5=8C=96-=E5=A4=A7?= =?UTF-8?q?=E7=BB=93=E5=B1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zuolaos/jichuban/Code02_二分法.java | 90 +- .../zuolaos/jichuban/Code19_暴力递归.java | 58 ++ .../zuolaos/jichuban/Code20_动态规划.java | 845 ++++++++++++++++++ 3 files changed, 982 insertions(+), 11 deletions(-) create mode 100644 src/test/java/zuolaos/jichuban/Code19_暴力递归.java create mode 100644 src/test/java/zuolaos/jichuban/Code20_动态规划.java diff --git a/src/test/java/zuolaos/jichuban/Code02_二分法.java b/src/test/java/zuolaos/jichuban/Code02_二分法.java index f687c91..6090417 100644 --- a/src/test/java/zuolaos/jichuban/Code02_二分法.java +++ b/src/test/java/zuolaos/jichuban/Code02_二分法.java @@ -1,11 +1,13 @@ package zuolaos.jichuban; -import java.util.Arrays; +import org.omg.CORBA.PUBLIC_MEMBER; public class Code02_二分法 { +} - public static int m1(int[] arr, int num) { +class 等于的数 { + public int m1(int[] arr, int num) { if (arr == null || arr.length == 0) { return -1; } @@ -25,10 +27,10 @@ public class Code02_二分法 { } return ans; } +} - - // >=num 最左的数 - public static int m2(int[] arr, int num) { +class 最左的数 { + public int m2(int[] arr, int num) { if (arr == null || arr.length == 0) { return -1; } @@ -47,9 +49,10 @@ public class Code02_二分法 { return ans; } +} - // <=num 最右的数 - public static int m3(int[] arr, int num) { +class 最右的数 { + public int m3(int[] arr, int num) { if (arr == null || arr.length == 0) { return -1; } @@ -67,13 +70,78 @@ public class Code02_二分法 { } return ans; } +} + +class 两个数组得到中位数 { + public int process(int[] arr1, int[] arr2) { + + int N1 = arr1.length; + int N2 = arr2.length; + int K = N1 + N2; + if ((K & 1) == 0) { + return (f(arr1, arr2, K / 2) + f(arr1, arr2, K / 2 + 1)) / 2; + } else { + return f(arr1, arr2, K / 2 + 1); + } + } public static void main(String[] args) { - int[] ints = Code00_对数器.generateRandomArray(10, 60); - Arrays.sort(ints); - ints[7] = ints[8]; - System.out.println(m3(ints, ints[8])); + 两个数组得到中位数 aaa = new 两个数组得到中位数(); + int[] arr1 = {1, 2, 3}; + int[] arr2 = {4, 5}; + System.out.println(aaa.process(arr1, arr2)); + System.out.println(aaa.f(arr1, 0, arr1.length - 1, arr2, 0, arr2.length - 1, 3)); } + public int f(int[] arr1, int start1, int end1, int[] arr2, int start2, int end2, int k) { + int len1 = end1 - start1 + 1; + int len2 = end2 - start2 + 1; + if (start1 > end1) { + return arr2[start2 + k - 1]; + } + if (start2 > end2) { + return arr1[start1 + k - 1]; + } + if (k == 1) { + return Math.min(arr1[start1], arr2[start2]); + } + int i = start1 + Math.min(k / 2, len1) - 1; + int j = start2 + Math.min(k / 2, len2) - 1; + if (arr1[i] <= arr2[j]) { + return f(arr1, i + 1, end1, arr2, start2, end2, k - (i - start1 + 1)); + } else { + return f(arr1, start1, end1, arr2, j + 1, end2, k - (j - start2 + 1)); + } + } + + private int f(int[] arr1, int[] arr2, int k) { + //1.不越界 每个数组需要找到k/2 个数 对应的索引位置 + int L1 = 0; + int L2 = 0; + int index1 = 0; + int index2 = 0; + while (true) { + index1 = Math.min(L1 + k / 2, arr1.length) - 1; + index2 = Math.min(L2 + k / 2, arr2.length) - 1; + + if (arr1[index1] <= arr2[index2]) { + //丢弃 + k -= index1 - L1 + 1; + L1 = index1 + 1; + } else { + k -= index2 - L2 + 1; + L2 = index2 + 1; + } + if (L1 > arr1.length - 1) { + return arr2[L2 + k - 1]; + } + if (L2 > arr2.length - 1) { + return arr1[L1 + k - 1]; + } + if (k == 1) { + return Math.min(arr1[L1], arr2[L2]); + } + } + } } diff --git a/src/test/java/zuolaos/jichuban/Code19_暴力递归.java b/src/test/java/zuolaos/jichuban/Code19_暴力递归.java new file mode 100644 index 0000000..6be67dd --- /dev/null +++ b/src/test/java/zuolaos/jichuban/Code19_暴力递归.java @@ -0,0 +1,58 @@ +package zuolaos.jichuban; + +import java.util.List; + +public class Code19_暴力递归 { +} + + +class 移动圆盘 { + public void process(int N, String from, String to, String other) { + if (N == 1) { + System.out.println("move " + "1" + " form " + from + " to " + to); + return; + } + + process(N - 1, from, other, to); + System.out.println("move " + N + " form " + from + " to " + to); + process(N - 1, other, to, from); + + } + + public static void main(String[] args) { + new 移动圆盘().process(3, "from", "to", "other"); + } +} + +class 字符串全部子序列 { + public void process(char[] str, int index, String path, List ans) { + if (index == str.length) { + ans.add(path); + return; + } + process(str, index + 1, path, ans); + process(str, index + 1, path + str[index], ans); + } +} + +class 字符串不同排列 { + + public void process(char[] str, int index, List ans) { + if (index == str.length) { + ans.add(String.valueOf(str)); + return; + } + for (int i = index; i < str.length; i++) { + //index 和后面的交换 + process(str, i, ans); + //index 和后面的交换回来 恢复现场 + } + + } + +} + + + + + diff --git a/src/test/java/zuolaos/jichuban/Code20_动态规划.java b/src/test/java/zuolaos/jichuban/Code20_动态规划.java new file mode 100644 index 0000000..9bd34b6 --- /dev/null +++ b/src/test/java/zuolaos/jichuban/Code20_动态规划.java @@ -0,0 +1,845 @@ +package zuolaos.jichuban; + + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +public class Code20_动态规划 { +} + +class 机器人到达指定位置 { + + public int process1(int cur, int rest, int aim, int N) { + if (rest == 0) { + return cur == aim ? 1 : 0; + } + if (cur == 1) { + return process1(2, rest - 1, aim, N); + } + if (cur == N) { + return process1(N - 1, rest - 1, aim, N); + } + return process1(cur + 1, rest - 1, aim, N) + process1(cur - 1, rest - 1, aim, N); + } + + + public int process2(int cur, int rest, int aim, int N, int[][] dp) { + if (dp[cur][rest] != -1) { + return dp[cur][rest]; + } + int ans = 0; + if (rest == 0) { + ans = cur == aim ? 1 : 0; + } else if (cur == 1) { + ans = process2(2, rest - 1, aim, N, dp); + } else if (cur == N) { + ans = process2(N - 1, rest - 1, aim, N, dp); + } else { + ans = process2(cur + 1, rest - 1, aim, N, dp) + process2(cur - 1, rest - 1, aim, N, dp); + } + dp[cur][rest] = ans; + return ans; + } + + + public int process3(int start, int K, int aim, int N) { + int[][] dp = new int[N + 1][K + 1]; + dp[aim][0] = 1; + for (int rest = 1; rest < K + 1; rest++) { + dp[1][rest] = dp[2][rest - 1]; + for (int cur = 2; cur < N; cur++) { + dp[cur][rest] = dp[cur - 1][rest - 1] + dp[cur + 1][rest - 1]; + } + dp[N][rest] = dp[N - 1][rest - 1]; + } + return dp[start][K]; + } + + public static void main(String[] args) { + 机器人到达指定位置 aaa = new 机器人到达指定位置(); + System.out.println(aaa.process1(2, 4, 4, 6)); + System.out.println(aaa.process3(2, 4, 4, 6)); + } + + +} + +class 先后手取牌 { + public static void main(String[] args) { + 先后手取牌 aaa = new 先后手取牌(); + int[] arr = {10, 20, 30, 40, 50, 600}; + int R = arr.length; + int[][] fdp = new int[R][R]; + int[][] gdp = new int[R][R]; + for (int i = 0; i < R; i++) { + for (int j = 0; j < R; j++) { + fdp[i][j] = -1; + gdp[i][j] = -1; + } + } + int f = aaa.f(arr, 0, arr.length - 1, fdp, gdp); + int g = aaa.g(arr, 0, arr.length - 1, fdp, gdp); + System.out.println(f + "..." + g); + System.out.println(aaa.process(arr)); + } + + public int f(int[] arr, int L, int R, int[][] fdp, int[][] gdp) { + if (fdp[L][R] != -1) { + return fdp[L][R]; + } + int ans = 0; + if (L == R) { + ans = arr[L]; + } else { + int p1 = arr[L] + g(arr, L + 1, R, fdp, gdp); + int p2 = arr[R] + g(arr, L, R - 1, fdp, gdp); + ans = Math.max(p1, p2); + } + fdp[L][R] = ans; + return ans; + } + + public int g(int[] arr, int L, int R, int[][] fdp, int[][] gdp) { + if (gdp[L][R] != -1) { + return gdp[L][R]; + } + int ans = 0; + if (L != R) { + int p1 = f(arr, L, R - 1, fdp, gdp); + int p2 = f(arr, L + 1, R, fdp, gdp); + ans = Math.min(p1, p2); + + } + gdp[L][R] = ans; + return ans; + } + + + public int process(int[] arr) { + int N = arr.length; + int[][] fdp = new int[N][N]; + int[][] gdp = new int[N][N]; + for (int i = 0; i < N; i++) { + fdp[i][i] = arr[i]; + } + + for (int start = 1; start < N; start++) { + int L = 0; + int R = start; + while (R < N) { + fdp[L][R] = Math.max(arr[L] + gdp[L + 1][R], arr[R] + gdp[L][R - 1]); + gdp[L][R] = Math.min(fdp[L][R - 1], fdp[L + 1][R]); + L++; + R++; + } + } + return Math.max(fdp[0][N - 1], gdp[0][N - 1]); + } + + +} + +class 背包问题 { + + public int process(int[] v, int[] w, int index, int bag) { + if (bag < 0) { + return 0; + } + if (index == w.length) { + return 0; + } + + int p1 = process(v, w, index + 1, bag); + int p2 = 0; + if (bag < w[index]) { + p2 = 0; + } else { + p2 = process(v, w, index + 1, bag - w[index]) + v[index]; + } + return Math.max(p1, p2); + } + + + public int dp(int[] v, int[] w, int rest) { + + int N = w.length; + int[][] dp = new int[N + 1][rest + 1]; + for (int index = N - 1; index >= 0; index--) { + for (int bag = 0; bag < rest; bag++) { + int p1 = dp[index + 1][bag]; + int p2 = bag < w[index] ? 0 : dp[index + 1][bag - w[index]] + v[index]; + dp[index][rest] = Math.max(p1, p2); + } + } + return dp[0][rest]; + } + + +} + +class 数字字符转换 { + + public int process(char[] str, int i) { + if (i == str.length) { + return 1; + } + if (str[i] == '0') { + return 0; + } + int p1 = process(str, i + 1); + if (i + 1 < str.length && (str[i] - '0') * 10 + (str[i + 1] - '0') < 27) { + p1 += process(str, i + 2); + } + return p1; + } + + public int dp(char[] str) { + int N = str.length; + int[] dp = new int[N + 1]; + dp[N] = 1; + for (int i = N - 1; i >= 0; i--) { + int ans = 0; + if (str[i] != '0') { + ans = dp[i + 1]; + if (i + 1 < str.length && (str[i] - '0') * 10 + (str[i + 1] - '0') < 27) { + ans += dp[i + 2]; + } + } + dp[i] = ans; + } + return dp[0]; + } + + +} + +class 使用贴纸组合形成字符串 { + + public int process1(String target, String[] tiks) { + if (target.length() == 0) { + return 0; + } + + int min = Integer.MAX_VALUE; + for (String first : tiks) { + //减少target 字符串的数量 + String rest = filterStr(target, first); + if (rest.length() != target.length()) { + min = Math.min(min, process1(rest, tiks)); + } + } + if (min == Integer.MAX_VALUE) { + return min; + } else { + return min + 1; + } + } + + + // tiks 表示某个字帖 中具体字符出现的数量 + public int process2(String target, int[][] tiks) { + if (target.length() == 0) { + return 0; + } + char[] chars = target.toCharArray(); + int[] tcount = new int[26]; + for (char ch : chars) { + tcount[ch - 'a']++; + } + int min = Integer.MAX_VALUE; + for (int[] first : tiks) { + //减少target 字符串的数量 + if (first[chars[0] - 'a'] > 0) { + for (int i = 0; i < 26; i++) { + if (tcount[i] > 0) { + int num = tcount[i] - first[i]; + StringBuilder rest = new StringBuilder(); + while (num > 0) { + rest.append((char) (i + 'a')); + num--; + } + } + } + min = Math.min(min, process2("", tiks)); + } + } + if (min == Integer.MAX_VALUE) { + return min; + } else { + return min + 1; + } + } + + + // tiks 表示某个字帖 中具体字符出现的数量 + public int process3(String target, int[][] tiks, Map dp) { + if (dp.containsKey(target)) { + return dp.get(target); + } + if (target.length() == 0) { + return 0; + } + char[] chars = target.toCharArray(); + int[] tcount = new int[26]; + for (char ch : chars) { + tcount[ch - 'a']++; + } + int min = Integer.MAX_VALUE; + for (int[] first : tiks) { + //减少target 字符串的数量 + if (first[chars[0] - 'a'] > 0) { + for (int i = 0; i < 26; i++) { + if (tcount[i] > 0) { + int num = tcount[i] - first[i]; + StringBuilder rest = new StringBuilder(); + while (num > 0) { + rest.append((char) (i + 'a')); + num--; + } + } + } + min = Math.min(min, process2("", tiks)); + } + } + min = min + min == Integer.MAX_VALUE ? 0 : 1; + dp.put(target, min); + return min; + } + + + private String filterStr(String target, String first) { + char[] chars1 = target.toCharArray(); + char[] chars2 = first.toCharArray(); + int[] count = new int[26]; + for (char c : chars1) { + count[c - 'a']++; + } + for (char c : chars2) { + count[c - 'a']--; + } + StringBuilder str = new StringBuilder(); + + for (int i = 0; i < 26; i++) { + while (count[i] > 0) { + str.append((char) ('a' + i)); + count[i]--; + } + } + + return str.toString(); + } + + +} + +class 二维数组最佳路径 { + + public int process(int[][] m) { + if (m == null || m.length == 0 || m[0] == null || m[0].length == 0) { + return 0; + } + + int row = m.length; + int col = m[0].length; + int[] dp = new int[col]; + dp[0] = m[0][0]; + for (int j = 1; j < col; j++) { + dp[j] += dp[j - 1] + m[0][j]; + } + + for (int i = 1; i < row; i++) { + dp[0] += m[i][0]; + for (int j = 1; j < col; j++) { + dp[i] = Math.min(dp[j - 1], dp[j]) + m[i][j]; + } + } + return dp[col - 1]; + } + +} + +class 数组中组成固定和的方法数 { + + public int process(int[] arr, int index, int rest) { + if (rest < 0) { + return 0; + } + if (index == arr.length) { + return rest == 0 ? 1 : 0; + } + //选你 + int p1 = process(arr, index + 1, rest - arr[index]); + //不选你 + int p2 = process(arr, index + 1, rest); + return p1 + p2; + } + + public int dp(int[] arr, int aim) { + if (aim == 0) { + return 1; + } + int row = arr.length; + int col = aim; + int[][] dp = new int[row + 1][col + 1]; + dp[row][0] = 1; + for (int index = row - 1; index >= 0; index--) { + for (int rest = 0; rest <= aim; rest++) { + dp[index][rest] = dp[index + 1][rest] + (rest - arr[index]) >= 0 ? dp[index + 1][rest - arr[index]] : 0; + } + } + return dp[0][aim]; + } +} + +class 数组中组成固定和的方法数可重复选 { + public int process(int[] arr, int index, int rest) { + if (index == arr.length) { + return rest == 0 ? 1 : 0; + } + int ways = 0; + for (int zhang = 0; zhang * arr[index] <= rest; zhang++) { + ways += process(arr, index + 1, rest - zhang * arr[index]); + } + return ways; + } + + public int dp(int[] arr, int aim) { + if (aim == 0) { + return 1; + } + int N = arr.length; + int[][] dp = new int[N + 1][aim + 1]; + dp[N][0] = 1; + for (int index = N - 1; index >= 0; index--) { + for (int rest = 0; rest <= aim; rest++) { + int ways = 0; + for (int zhang = 0; zhang * arr[index] <= rest; zhang++) { + ways += dp[index + 1][rest - zhang * arr[index]]; + } + dp[index][rest] = ways; + } + } + return dp[0][aim]; + } + + + public int dp2(int[] arr, int aim) { + if (aim == 0) { + return 1; + } + int N = arr.length; + int[][] dp2 = new int[N + 1][aim + 1]; + dp2[N][0] = 1; + for (int index = N - 1; index >= 0; index--) { + for (int rest = 0; rest <= aim; rest++) { + dp2[index][rest] = (rest - arr[index]) >= 0 ? dp2[index][rest - arr[index]] : 0 + dp2[index + 1][rest]; + } + } + return dp2[0][aim]; + } +} + +class 数组中组成固定和的方法数重复选的个数确定 { + + class Info { + public int[] zhangs; + public int[] amounts; + + public Info(int[] zhangs, int[] amounts) { + this.zhangs = zhangs; + this.amounts = amounts; + } + } + + public int process(int[] arr, int aim) { + if (aim == 0) { + return 1; + } + Info info = getInfo(arr); + return f(info.amounts, info.zhangs, 0, aim); + } + + private int f(int[] amounts, int[] zhangs, int index, int rest) { + if (index == zhangs.length) { + return rest == 0 ? 1 : 0; + } + + int ways = 0; + for (int zhang = 0; zhang * amounts[index] <= rest && zhang <= zhangs[index]; zhang++) { + ways += f(amounts, zhangs, index + 1, rest - zhang * amounts[index]); + } + return ways; + } + + public int dp(int[] arr, int aim) { + if (aim == 0) { + return 1; + } + Info info = getInfo(arr); + + int[] amounts = info.amounts; + int[] zhangs = info.zhangs; + int N = zhangs.length; + + int[][] dp = new int[N + 1][aim + 1]; + dp[N][0] = 1; + + for (int index = N - 1; index >= 0; index--) { + for (int rest = 0; rest <= aim; rest++) { +// int ways = 0; +// for (int zhang = 0; zhang * amounts[index] <= rest && zhang <= zhangs[index]; zhang++) { +// ways += dp[index + 1][rest - zhang * amounts[index]]; +// } +// dp[index][rest] = ways; + //判断和左边位置的依赖关系 当前=左+下-不越界的下左 + dp[index][rest] += dp[index + 1][rest]; + //左不越界 + if (rest - amounts[index] >= 0) { + dp[index][rest] += dp[index][rest - amounts[index]]; + } + //最左的张数不越界 + if (rest - (zhangs[index] + 1) * amounts[index] >= 0) { + dp[index][rest] -= dp[index + 1][rest - (zhangs[index] + 1) * amounts[index]]; + } + } + } + + return dp[0][aim]; + + } + + private Info getInfo(int[] arr) { + Map map = new HashMap<>(); + for (int amount : arr) { + if (map.containsKey(amount)) { + Integer count = map.get(amount); + map.put(amount, count + 1); + } else { + map.put(amount, 1); + } + } + Set amountSet = map.keySet(); + int size = amountSet.size(); + int[] zhangs = new int[size]; + int[] amounts = new int[size]; + int index = 0; + for (Integer amount : amountSet) { + amounts[index] = map.get(amount); + zhangs[index] = amount; + index++; + } + return new Info(zhangs, amounts); + } +} + +class 英雄砍死怪兽的概率 { + + + public double process(int hp, int times, int M) { + if (hp < 1 || times < 1 || M < 1) { + return 0; + } + double all = Math.pow((M + 1), times); + double kill = f(hp, times, M);//存活下来的情况 + return 1 - kill / all; + } + + + public double dp(int hp, int times, int M) { + if (hp < 1 || times < 1 || M < 1) { + return 0; + } + double all = Math.pow((M + 1), times); + int[][] dp = new int[times + 1][hp + 1]; + for (int i = 1; i <= hp; i++) { + dp[0][i] = 1; + } + for (int index = 1; index <= times; index++) { + for (int h = 1; h <= hp; h++) { +// int ways = 0; +// for (int i = 0; i <= M; i++) { +// ways += (h - i) >= 0 ? dp[index - 1][h - i] : 0; +// } +// dp[index][h] = ways; + dp[index][h] = dp[index - 1][h] + dp[index][h - 1]; + if (h - M - 1 >= 0) { + dp[index][h] -= dp[index - 1][h - M - 1]; + } + } + } + System.out.println(dp[times][hp]); + System.out.println(all); + return (double) (all - dp[times][hp]) / (double) all; + } + + private double f(int hp, int times, int M) { + if (0 == times) { + return hp > 0 ? 1 : 0; + } + if (hp <= 0) { + return 0; + } + + int ways = 0; + for (int i = 0; i <= M; i++) { + ways += f(hp - i, times - 1, M); + } + return ways; + } + + + public static void main(String[] args) { + 英雄砍死怪兽的概率 aaa = new 英雄砍死怪兽的概率(); + + System.out.println(aaa.dp(30, 3, 10)); +// System.out.println(aaa.process(10, 1, 10)); + } + +} + + +class 数组中组成固定和可重复选的个数最少 { + + + public int process(int[] arr, int index, int rest) { + if (index == arr.length) { + return rest == 0 ? 0 : Integer.MAX_VALUE; + } + int ways = Integer.MAX_VALUE; + for (int zhang = 0; zhang * arr[index] <= rest; zhang++) { + int next = process(arr, index + 1, rest - zhang * arr[index]); + if (next != Integer.MAX_VALUE) { + ways = Math.min(ways, next + zhang); + } + } + return ways; + } + + public int dp(int[] arr, int aim) { + int N = arr.length; + + int[][] dp = new int[N + 1][aim + 1]; + dp[N][0] = 0; + for (int i = 1; i <= aim; i++) { + dp[N][i] = Integer.MAX_VALUE; + } + for (int index = N - 1; index >= 0; index--) { + for (int rest = 0; rest <= aim; rest++) { + dp[index][rest] = dp[index + 1][rest]; + if (rest - arr[index] >= 0 && dp[index][rest - arr[index]] != Integer.MAX_VALUE) { + dp[index][rest] = Math.min(dp[index][rest], dp[index][rest - arr[index] + 1]); + } + } + } + return dp[0][aim]; + } +} + +class 数字的分裂的个数 { + + //precess(1,N) + public int process(int pre, int rest) { + if (rest == 0) { + return 1; + } + if (pre > rest) { + return 0; + } + int ways = 0; + for (int i = pre; i <= rest; i++) { + ways += process(i, rest - i); + } + return ways; + } + + + public int dp(int N) { + if (N <= 0) { + return 0; + } + if (N == 1) { + return 1; + } + + int[][] dp = new int[N + 1][N + 1]; + for (int i = 1; i <= N; i++) { + dp[i][0] = 1; + dp[i][i] = 1; + } + for (int pre = N - 1; pre > 0; pre--) { + for (int rest = pre + 1; rest <= N; rest++) { +// int ways = 0; +// for (int i = pre; i <= rest; i++) { +// ways += dp[i][rest - i]; +// } +// dp[pre][rest] = ways; + dp[pre][rest] = dp[pre + 1][rest] + dp[pre][rest - pre]; + } + } + return dp[1][N]; + } +} + +class 拆分两个集合累加和接近 { + + public int process(int[] arr, int index, int sum, int targetSum) { + if (index == arr.length) { + return sum; + } + //不选i + int p1 = process(arr, index + 1, sum, targetSum); + //选i + int p2 = 0; + if (arr[index] + sum <= targetSum) { + p2 = process(arr, index + 1, sum + arr[index], targetSum); + } + return Math.max(p1, p2); + } + + public int process(int[] arr, int index, int targetSum) { + if (index == arr.length) { + return 0; + } + //不选i + int p1 = process(arr, index + 1, targetSum); + //选i + int p2 = 0; + if (arr[index] <= targetSum) { + p2 = arr[index] + process(arr, index + 1, targetSum - arr[index]); + } + return Math.max(p1, p2); + } + + + public int dp(int[] arr) { + if (arr == null || arr.length < 2) { + return 0; + } + int N = arr.length; + int sum = 0; + for (int num : arr) { + sum += num; + } + sum /= sum; + int[][] dp = new int[N + 1][sum + 1]; + + for (int index = N - 1; index >= 0; index--) { + for (int rest = 0; rest <= sum; rest++) { + //不选i + int p1 = dp[index + 1][rest]; + //选i + int p2 = 0; + if (arr[index] <= rest) { + p2 = arr[index] + dp[index + 1][rest - arr[index]]; + } + dp[index][rest] = Math.max(p1, p2); + } + } + return dp[0][sum]; + } + + public static void main(String[] args) { + 拆分两个集合累加和接近 aaa = new 拆分两个集合累加和接近(); + int[] arr = {1, 2, 3, 4}; + System.out.println(aaa.process(arr, 0, 0, 5)); + } +} + +class 拆分两个集合累加和接近个数一半 { + + public int m(int[] arr) { + if (arr == null || arr.length < 2) { + return 0; + } + int N = arr.length; + int sum = 0; + for (int num : arr) { + sum += num; + } + if ((N & 1) == 0) { + return process(arr, 0, sum / 2, N / 2); + } else { + return Math.max(process(arr, 0, sum / 2, N / 2), process(arr, 0, sum / 2, N / 2 + 1)); + } + } + + public int dp(int[] arr) { + if (arr == null || arr.length < 2) { + return 0; + } + int N = arr.length; + int sum = 0; + for (int num : arr) { + sum += num; + } + sum /= 2; + int num = (N + 1) / 2; + int[][][] dp = new int[N + 1][sum + 1][num + 1]; + + for (int i = 0; i < N; i++) { + for (int j = 0; j < sum; j++) { + for (int k = 0; k < num; k++) { + dp[i][j][k] = -1; + } + } + } + for (int j = 0; j < sum; j++) { + dp[N][j][0] = 0; + } + + for (int index = N - 1; index >= 0; index--) { + for (int rest = 0; rest < sum; rest++) { + for (int count = 0; count < num; count++) { + + int p1 = dp[index + 1][rest][count]; + int p2 = -1; + int next = -1; + if (count > 0 && arr[index] <= rest) { + next = dp[index + 1][rest - arr[index]][count - 1]; + } + if (next != -1) { + p2 = arr[index] + next; + } + dp[index][rest][count] = Math.max(p1, p2); + } + } + } + + if ((N & 1) == 0) { + return dp[0][sum][num]; + } else { + return Math.max(dp[0][sum][num], dp[0][sum][num - 1]); + } + } + + public int process(int[] arr, int index, int rest, int count) { + if (index == arr.length) { + return count == 0 ? 0 : -1; + } + int p1 = process(arr, index + 1, rest, count); + int p2 = -1; + int next = -1; + if (count > 0 && arr[index] <= rest) { + next = process(arr, index + 1, rest - arr[index], count - 1); + } + if (next != -1) { + p2 = arr[index] + next; + } + return Math.max(p1, p2); + } + + public static void main(String[] args) { + 拆分两个集合累加和接近个数一半 aaa = new 拆分两个集合累加和接近个数一半(); + int[] arr = {1, 2, 3, 4}; + System.out.println(aaa.process(arr, 0, 5, 2)); + } + +} + + + + + + +