Skip to content

Commit 6041ac9

Browse files
committed
add new problem
1 parent c0d73f8 commit 6041ac9

File tree

2 files changed

+228
-0
lines changed

2 files changed

+228
-0
lines changed
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
package class12;
2+
3+
import java.util.TreeSet;
4+
5+
/*
6+
* 给定一个整型数组arr,请把arr中所有的数分成两个集合,尽量让两个集合的累加和接近
7+
* 返回最接近的情况下,较小集合的累加和(较大集合的累加和一定是所有数累加和减去较小集合的累加和)
8+
* 为了方便起见,假设arr中没有负数,其实也可以有
9+
* 但是处理起来会比较麻烦,而且有没有负数都不影响算法流程的理解
10+
* */
11+
public class Code10_SplitSumClosed {
12+
13+
public static int right(int[] arr) {
14+
if (arr == null || arr.length < 2) {
15+
return 0;
16+
}
17+
int sum = 0;
18+
for (int num : arr) {
19+
sum += num;
20+
}
21+
TreeSet<Integer> ans = new TreeSet<>();
22+
process(arr, 0, 0, 0, ans, sum >> 1);
23+
return ans.last();
24+
}
25+
26+
public static void process(int[] arr, int i, int sum, int picks, TreeSet<Integer> ans, int limit) {
27+
if (i == arr.length) {
28+
if (sum <= limit) {
29+
ans.add(sum);
30+
}
31+
} else {
32+
process(arr, i + 1, sum, picks, ans, limit);
33+
process(arr, i + 1, sum + arr[i], picks + 1, ans, limit);
34+
}
35+
}
36+
37+
public static int dp(int[] arr) {
38+
if (arr == null || arr.length < 2) {
39+
return 0;
40+
}
41+
int sum = 0;
42+
for (int num : arr) {
43+
sum += num;
44+
}
45+
sum >>= 1;
46+
int N = arr.length;
47+
boolean[][] dp = new boolean[N][sum + 1];
48+
for (int i = 0; i < N; i++) {
49+
dp[i][0] = true;
50+
}
51+
if (arr[0] <= sum) {
52+
dp[0][arr[0]] = true;
53+
}
54+
for (int i = 1; i < N; i++) {
55+
for (int j = 1; j <= sum; j++) {
56+
dp[i][j] = dp[i - 1][j];
57+
if (j - arr[i] >= 0) {
58+
dp[i][j] |= dp[i - 1][j - arr[i]];
59+
}
60+
}
61+
}
62+
for (int j = sum; j >= 1; j--) {
63+
if (dp[N - 1][j]) {
64+
return j;
65+
}
66+
}
67+
return 0;
68+
}
69+
70+
public static int[] randomArray(int len, int value) {
71+
int[] arr = new int[len];
72+
for (int i = 0; i < arr.length; i++) {
73+
arr[i] = (int) (Math.random() * value);
74+
}
75+
return arr;
76+
}
77+
78+
public static void printArray(int[] arr) {
79+
for (int num : arr) {
80+
System.out.print(num + " ");
81+
}
82+
System.out.println();
83+
}
84+
85+
public static void main(String[] args) {
86+
int maxLen = 20;
87+
int maxValue = 50;
88+
int testTime = 10000;
89+
System.out.println("测试开始");
90+
for (int i = 0; i < testTime; i++) {
91+
int len = (int) (Math.random() * maxLen);
92+
int[] arr = randomArray(len, maxValue);
93+
int ans1 = right(arr);
94+
int ans2 = dp(arr);
95+
if (ans1 != ans2) {
96+
printArray(arr);
97+
System.out.println(ans1);
98+
System.out.println(ans2);
99+
System.out.println("Oops!");
100+
break;
101+
}
102+
}
103+
System.out.println("测试结束");
104+
}
105+
106+
}
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
package class12;
2+
3+
import java.util.TreeSet;
4+
5+
/*
6+
* 给定一个整型数组arr,请把arr中所有的数分成两个集合
7+
* 如果arr长度为偶数,两个集合包含数的个数要一样多
8+
* 如果arr长度为奇数,两个集合包含数的个数必须只差一个
9+
* 请尽量让两个集合的累加和接近
10+
* 返回最接近的情况下,较小集合的累加和(较大集合的累加和一定是所有数累加和减去较小集合的累加和)
11+
* 为了方便起见,假设arr中没有负数,其实也可以有
12+
* 但是处理起来会比较麻烦,而且有没有负数都不影响算法流程的理解
13+
* */
14+
public class Code11_SplitSumClosedSizeHalf {
15+
16+
public static int right(int[] arr) {
17+
if (arr == null || arr.length < 2) {
18+
return 0;
19+
}
20+
int sum = 0;
21+
for (int num : arr) {
22+
sum += num;
23+
}
24+
TreeSet<Integer> ans = new TreeSet<>();
25+
process(arr, 0, 0, 0, ans, sum >> 1);
26+
return ans.last();
27+
}
28+
29+
public static void process(int[] arr, int i, int sum, int picks, TreeSet<Integer> ans, int limit) {
30+
if (i == arr.length) {
31+
if ((arr.length & 1) == 0) {
32+
if (picks == (arr.length >> 1) && sum <= limit) {
33+
ans.add(sum);
34+
}
35+
} else {
36+
if ((picks == (arr.length >> 1) || picks == (arr.length >> 1) + 1) && sum <= limit) {
37+
ans.add(sum);
38+
}
39+
}
40+
} else {
41+
process(arr, i + 1, sum, picks, ans, limit);
42+
process(arr, i + 1, sum + arr[i], picks + 1, ans, limit);
43+
}
44+
}
45+
46+
public static int dp(int[] arr) {
47+
if (arr == null || arr.length < 2) {
48+
return 0;
49+
}
50+
int sum = 0;
51+
for (int num : arr) {
52+
sum += num;
53+
}
54+
sum >>= 1;
55+
int N = arr.length;
56+
int M = (arr.length + 1) >> 1;
57+
int[][][] dp = new int[N][M + 1][sum + 1];
58+
for (int i = 0; i < N; i++) {
59+
for (int j = 0; j <= M; j++) {
60+
for (int k = 0; k <= sum; k++) {
61+
dp[i][j][k] = Integer.MIN_VALUE;
62+
}
63+
}
64+
}
65+
for (int i = 0; i < N; i++) {
66+
for (int k = 0; k <= sum; k++) {
67+
dp[i][0][k] = 0;
68+
}
69+
}
70+
for (int k = 0; k <= sum; k++) {
71+
dp[0][1][k] = arr[0] <= k ? arr[0] : Integer.MIN_VALUE;
72+
}
73+
for (int i = 1; i < N; i++) {
74+
for (int j = 1; j <= Math.min(i + 1, M); j++) {
75+
for (int k = 0; k <= sum; k++) {
76+
dp[i][j][k] = dp[i - 1][j][k];
77+
if (k - arr[i] >= 0) {
78+
dp[i][j][k] = Math.max(dp[i][j][k], dp[i - 1][j - 1][k - arr[i]] + arr[i]);
79+
}
80+
}
81+
}
82+
}
83+
return Math.max(dp[N - 1][M][sum], dp[N - 1][N - M][sum]);
84+
}
85+
86+
public static int[] randomArray(int len, int value) {
87+
int[] arr = new int[len];
88+
for (int i = 0; i < arr.length; i++) {
89+
arr[i] = (int) (Math.random() * value);
90+
}
91+
return arr;
92+
}
93+
94+
public static void printArray(int[] arr) {
95+
for (int num : arr) {
96+
System.out.print(num + " ");
97+
}
98+
System.out.println();
99+
}
100+
101+
public static void main(String[] args) {
102+
int maxLen = 20;
103+
int maxValue = 50;
104+
int testTime = 10000;
105+
System.out.println("测试开始");
106+
for (int i = 0; i < testTime; i++) {
107+
int len = (int) (Math.random() * maxLen);
108+
int[] arr = randomArray(len, maxValue);
109+
int ans1 = right(arr);
110+
int ans2 = dp(arr);
111+
if (ans1 != ans2) {
112+
printArray(arr);
113+
System.out.println(ans1);
114+
System.out.println(ans2);
115+
System.out.println("Oops!");
116+
break;
117+
}
118+
}
119+
System.out.println("测试结束");
120+
}
121+
122+
}

0 commit comments

Comments
 (0)