数组所有可能子集的乘积之和
Sum of product of all possible subsets of array
我已经编写了一个代码来查找数组所有可能子集的乘积之和。我得到了预期的输出,但我无法使其足够快以清除与时间相关的测试用例。
谁能帮我优化我的代码以提高速度?
第一个输入(testCases)是测试用例的数量。
根据测试用例的数量,我们将得到数组的大小 (size) 和数组元素 (set)。
例如,有效输入为:
1
3
2 3 5
其中:
1
is the number of testcases. 3
is the size of the test set and 2 3 5
are the elements of the input set.
预期输出为:
71
以上输出的计算是:
{2}, {3}, {5}, {2, 3}, {3, 5}, {2, 5}, {2, 3, 5}
=> 2 3 5 6 15 10 30
=> 2 + 3 + 5 + 6 + 15 + 10 + 30
=> 71
import java.util.Scanner;
public class Test {
static int printSubsets(int set[]) {
int n = set.length;
int b = 0;
for (int i = 0; i < (1 << n); i++) {
int a = 1;
for (int j = 0; j < n; j++){
if ((i & (1 << j)) > 0) {
a *= set[j];
}}
b += a;
}
return b;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int testCases = scanner.nextInt();
for (int i = 0; i < testCases; i++) {
int size = scanner.nextInt();
int set[] = new int[size];
for (int j = 0; j < set.length; j++) {
set[j] = scanner.nextInt();
}
int c = printSubsets(set);
System.out.println((c - 1));
}
scanner.close();
}
}
你需要一点数学知识。假设您有 3 个值,就像您的示例一样,但我们称它们为 A
、B
和 C
.
要得到乘积之和,您需要计算:
Result3 = A + B + C + A*B + A*C + B*C + A*B*C
= A + B + A*B + (1 + A + B + A*B) * C
现在,如果我们先计算 A + B + A*B
,称它为 Result2
,那么你会得到:
Result2 = A + B + A*B
Result3 = Result2 + (1 + Result2) * C
我们重复一遍,所以
Result2 = A + (1 + A) * B
Result1 = A
Result2 = Result1 + (1 + Result1) * B
你能看出规律吗?让我们将其与 4 个值一起使用:
Result4 = A + B + C + D + A*B + A*C + A*D + B*C + B*D + C*D
+ A*B*C + A*B*D + A*C*D + B*C*D + A*B*C*D
= A + B + C + A*B + A*C + B*C + A*B*C
+ (1 + A + B + C + A*B + A*C + B*C + A*B*C) * D
= Result3 + (1 + Result3) * D
总结:
Result1 = A
Result2 = Result1 + (1 + Result1) * B
Result3 = Result2 + (1 + Result2) * C
Result4 = Result3 + (1 + Result3) * D
作为代码,这是:
private static long sumProduct(int... input) {
long result = 0;
for (int value : input)
result += (result + 1) * value;
return result;
}
只有一次迭代,所以O(n).
测试
System.out.println(sumProduct(2, 3));
System.out.println(sumProduct(2, 3, 5));
System.out.println(sumProduct(2, 3, 5, 7));
输出
11
71
575
更新
代码也可以使用 Java 8 Streams 和 Lambda 表达式来完成,使用 IntStream.of(int...)
or Arrays.stream(int[])
(他们做的相同)。
// Using IntStream with result as int
private static int sumProduct(int... input) {
return IntStream.of(input).reduce((a, b) -> a + (1 + a) * b).getAsInt();
}
// Using Arrays with result as long
private static long sumProduct(int... input) {
return Arrays.stream(input)
.asLongStream()
.reduce((a, b) -> a + (1 + a) * b)
.getAsLong();
}
我已经编写了一个代码来查找数组所有可能子集的乘积之和。我得到了预期的输出,但我无法使其足够快以清除与时间相关的测试用例。
谁能帮我优化我的代码以提高速度?
第一个输入(testCases)是测试用例的数量。 根据测试用例的数量,我们将得到数组的大小 (size) 和数组元素 (set)。
例如,有效输入为:
1
3
2 3 5
其中:
1
is the number of testcases.3
is the size of the test set and2 3 5
are the elements of the input set.
预期输出为:
71
以上输出的计算是:
{2}, {3}, {5}, {2, 3}, {3, 5}, {2, 5}, {2, 3, 5}
=> 2 3 5 6 15 10 30
=> 2 + 3 + 5 + 6 + 15 + 10 + 30
=> 71
import java.util.Scanner;
public class Test {
static int printSubsets(int set[]) {
int n = set.length;
int b = 0;
for (int i = 0; i < (1 << n); i++) {
int a = 1;
for (int j = 0; j < n; j++){
if ((i & (1 << j)) > 0) {
a *= set[j];
}}
b += a;
}
return b;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int testCases = scanner.nextInt();
for (int i = 0; i < testCases; i++) {
int size = scanner.nextInt();
int set[] = new int[size];
for (int j = 0; j < set.length; j++) {
set[j] = scanner.nextInt();
}
int c = printSubsets(set);
System.out.println((c - 1));
}
scanner.close();
}
}
你需要一点数学知识。假设您有 3 个值,就像您的示例一样,但我们称它们为 A
、B
和 C
.
要得到乘积之和,您需要计算:
Result3 = A + B + C + A*B + A*C + B*C + A*B*C
= A + B + A*B + (1 + A + B + A*B) * C
现在,如果我们先计算 A + B + A*B
,称它为 Result2
,那么你会得到:
Result2 = A + B + A*B
Result3 = Result2 + (1 + Result2) * C
我们重复一遍,所以
Result2 = A + (1 + A) * B
Result1 = A
Result2 = Result1 + (1 + Result1) * B
你能看出规律吗?让我们将其与 4 个值一起使用:
Result4 = A + B + C + D + A*B + A*C + A*D + B*C + B*D + C*D
+ A*B*C + A*B*D + A*C*D + B*C*D + A*B*C*D
= A + B + C + A*B + A*C + B*C + A*B*C
+ (1 + A + B + C + A*B + A*C + B*C + A*B*C) * D
= Result3 + (1 + Result3) * D
总结:
Result1 = A
Result2 = Result1 + (1 + Result1) * B
Result3 = Result2 + (1 + Result2) * C
Result4 = Result3 + (1 + Result3) * D
作为代码,这是:
private static long sumProduct(int... input) {
long result = 0;
for (int value : input)
result += (result + 1) * value;
return result;
}
只有一次迭代,所以O(n).
测试
System.out.println(sumProduct(2, 3));
System.out.println(sumProduct(2, 3, 5));
System.out.println(sumProduct(2, 3, 5, 7));
输出
11
71
575
更新
代码也可以使用 Java 8 Streams 和 Lambda 表达式来完成,使用 IntStream.of(int...)
or Arrays.stream(int[])
(他们做的相同)。
// Using IntStream with result as int
private static int sumProduct(int... input) {
return IntStream.of(input).reduce((a, b) -> a + (1 + a) * b).getAsInt();
}
// Using Arrays with result as long
private static long sumProduct(int... input) {
return Arrays.stream(input)
.asLongStream()
.reduce((a, b) -> a + (1 + a) * b)
.getAsLong();
}