java - Map 中的PosibleSums 与Java 8 中给定的双精度或双精度数组列表
问题描述
下面的代码给出了给定双数组的所有可能总和,如何对 java8 流执行相同操作并在 `Map<Integer,Double[]> 中产生结果,如下所示
(0,[15],[0.55])
没有地图实现的代码:
public class PossibleDoubleSums {
public static void getAllSums(double []arr, double startingValue, int pos ) {
for (int i = pos; i < arr.length; i++) {
double currentValue = startingValue + arr[i];
System.out.println(currentValue+"");
getAllSums(arr, currentValue, i + 1);
}
}
public static void main(String[] args) {
double arr[] = {15.00, 0.55,25.00, 7.00};
getAllSums(arr, 0, 0 ); // Test array
}
}
解决方案
返回可能的总和
class Solution {
public static List<Double> solve(double[] arr) {
return IntStream.range(0, 1 << arr.length).boxed()
.filter(n -> (n & (n - 1)) != 0)
.map(n -> IntStream.range(0, arr.length)
.filter(i -> ((n >> i) & 1) == 1)
.mapToDouble(i -> arr[i])
.sum())
.collect(Collectors.toList());
}
}
用法
final double[] arr = { 15.00, 0.55, 25.00, 7.00 };
System.out.println(solve(arr));
// Outputs [15.55, 40.0, 25.55, 40.55, 22.0, 7.55, 22.55, 32.0, 47.0, 32.55, 47.55]
返回可能的对
class Solution {
public static List<Double[]> solve(double[] arr) {
return IntStream.range(0, 1 << arr.length).boxed()
.filter(n -> (n & (n - 1)) != 0)
.map(n -> IntStream.range(0, arr.length).boxed()
.filter(i -> ((n >> i) & 1) == 1)
.map(i -> arr[i])
.toArray(Double[]::new))
.collect(Collectors.toList());
}
}
用法
final double[] arr = { 15.00, 0.55, 25.00, 7.00 };
final List<Double[]> result = solve(arr);
for (Double[] resultArr : result) {
System.out.println(Arrays.toString(resultArr));
}
输出
[15.0, 0.55]
[15.0, 25.0]
[0.55, 25.0]
[15.0, 0.55, 25.0]
[15.0, 7.0]
[0.55, 7.0]
[15.0, 0.55, 7.0]
[25.0, 7.0]
[15.0, 25.0, 7.0]
[0.55, 25.0, 7.0]
[15.0, 0.55, 25.0, 7.0]
解释
{15.00, 0.55, 25.00, 7.00}
让我们使用作为输入数组来分解它:
IntStream.range(0, 1 << arr.length)
创建一个从 0 到 的值流1 << arr.length
。表达式1 << n
与 相同Math.pow(n, 2)
,因此1 << arr.length
等于 16。
现在的流是IntStream({0, 1, 2, 3, ..., 12, 13, 14, 15})
.
boxed()
将此转换IntStream
为Stream<Integer>
. 这允许我们最终将其转换为 aList<Integer>
。
现在的流是Stream<Integer>({0, 1, 2, 3, ..., 12, 13, 14, 15})
.
filter(n -> (n & (n - 1)) != 0)
从流中删除所有 2 的幂元素,包括 0(说明)。为什么是这样?让我们看一下当前流的二进制表示:{0000, 0001, 0010, 0011, 0100, 0101, 0110, 0111, 1000, 1001, 1010, 1011, 1100, 1101, 1110, 1111}
现在将每个位分配给其各自的数组元素:数字
0110
对应于元素{0.55, 25.00}
,数字0001
对应于元素{7.00}
,数字1111
对应于所有元素 ({15.00, 0.55, 25.00, 7.00}
),因为所有位都已设置。根据您的测试用例,我们不能在输出数组中包含输入数字(例如,输出数组中不应包含 15.0、0.55、25 或 7)。因此,我们不能包含包含单个位的数字(例如
0001
或0100
)。这些数字是 2 的幂,因此我们必须删除它们。
现在的流是Stream<Integer>({3, 5, 6, 7, ..., 12, 13, 14, 15})
.
map(...)
将此流的元素映射到另一种类型。对于每个元素n
(假设n
等于 6),IntStream.range(0, arr.length)
创建一个从 0 到 4 的流。
现在的子流是
IntStream({0, 1, 2, 3})
.filter(i -> ((n >> i) & 1) == 1)
仅保留为 1 的位的索引。
现在的子流是
IntStream({1, 2})
. 注意n
等于 6,其二进制表示为0110
。由于设置了中间两位,因此将保留输入数组中的中间两位元素。mapToDouble(i -> arr[i])
将每个位映射到输入数组中的相应元素。
现在的子流是
IntStream({0.55, 25.00})
.sum()
对来自该流的所有元素求和。
结果是
25.55
。collect(Collectors.toList())
将为此流中的所有元素重复第 4 步,返回一个List<Double>
.
结果是[15.55, 40.0, 25.55, 40.55, 22.0, 7.55, 22.55, 32.0, 47.0, 32.55, 47.55]
。
推荐阅读
- android - 底部导航栏不显示图标或文本
- ruby-on-rails - Ruby on Rails - 显示具有不同内容的相同模式
- python - 如何在 Python 中绘制多个时间序列
- javascript - 想在reactjs中将数据从父组件传递给子组件
- c# - 为什么 SqlDependency 对象无法检测到 SQL Server 表的变化?
- xcode - 如何将 Xcode 更新到 9.3 和 mac sierra
- php - codeigniter 使用通配符(任意)路由固定字符串或字符
- java - 使用 Java 中的任务调度程序更新表时行被锁定
- prolog - 给定带有成员谓词的查询,回溯如何工作的混乱
- java - 如何在列表视图上添加对象?