【问题标题】:How can I use an IntStream to sum specific indexed numbers of an int array?如何使用 IntStream 对 int 数组的特定索引数求和?
【发布时间】:2018-12-19 21:42:33
【问题描述】:

我一直在使用 lambda 学习 Kotlin 和 Java。尽管我不太了解函数式编程,但我正在尝试尽可能多地使用函数式编程。

我正在使用 HackerRank 的问题来研究(以及 Koans 来研究 Kotlin)。我目前正在使用 Kotlin 和 Java 8 解决问题。

我正在尝试解决MiniMax-Sum problem。基本上,描述是这样的:

给定五个正整数,找出可以通过将五个整数中的四个恰好相加来计算的最小值和最大值。然后将各自的最小值和最大值打印为一行,由两个空格分隔的长整数组成。

我正在尝试在 Java 中尽可能多地使用流 API。一个简单的问题是:在排序后,如何将 int 数组减少为其四个第一个元素(最后一个,在不同的场景中)并将其值求和?我尝试使用IntStream,但不使用List 似乎非常困难。我想知道是否可以直接使用 int[] 数组和 IntStream 来排序和减少元素并将它们相加。

使用 Kotlin 我解决了这样的问题:

val minSum: Long = arr.sortedArray().copyOfRange(0, 4).sum().toLong()
val maxSum: Long = arr.sortedArray().copyOfRange(1, 5).sum().toLong()
println("$minSum $maxSum")

我正在尝试使用range 方法以及sortedsum。有用。问题是总和总是返回一个int,有时总和是一个long 值。这是我的代码:

long min = IntStream.range(0, arr.length)
        .sorted()
        .sum();

long max = IntStream.range(1, arr.length + 1)
        .sorted()
        .sum();

输入 new long[] {256741038, 623958417, 467905213, 714532089, 938071625} 的结果为 10(最小值)和 15(最大值)


非常感谢所有花时间提供帮助的人!我猜我没有看到 LongStream.of 方法:D 我使用 2 种不同的方法解决了(@Aomine、@nullpointer 和 @Holger 指出):

// using Arrays and Stream
Arrays.sort(arr);
long min = Arrays.stream(arr, 0, 4).sum();
long max = Arrays.stream(arr, 1, 5).sum();

System.out.println(min + " " + max);

// and using LongSummaryStatistics (thanks @Holger)
LongSummaryStatistics ls = LongStream.of(arr).summaryStatistics();
System.out.println((ls.getSum() - ls.getMax()) + " " + (ls.getSum() - ls.getMin()));

非常感谢大家!

【问题讨论】:

    标签: java lambda java-stream


    【解决方案1】:

    虽然您可以通过排序来解决此任务,但如其他答案所示,这是不必要的工作。 “五分之四相加”的意思是“除了一个之外的所有值相加”,所以你所要做的就是从所有元素的总和中减去一个元素。减去最大的元素得到最小的四和,减去最小的元素得到最大的四和:

    IntSummaryStatistics s = IntStream.of(1, 3, 5, 7, 9).summaryStatistics();
    System.out.printf("%d %d%n", s.getSum()-s.getMax(), s.getSum()-s.getMin());
    
    16 24
    

    或者,如果源是一个数组:

    IntSummaryStatistics s = Arrays.stream(array).summaryStatistics();
    System.out.printf("%d %d%n", s.getSum()-s.getMax(), s.getSum()-s.getMin());
    

    【讨论】:

    • 我可能把问题放错了,@nullpointer。感谢您的帮助!
    【解决方案2】:

    你可能只是在寻找类似Intstream.range(int startInclusive, int endExclusive)的东西

    startInclusive(含)返回一个顺序有序的 IntStream 到endExclusive(独占),增量为1。

    在这些之上,您可以直接执行sum 或使用IntSummaryStatisticssummaryStatistics() 来进一步访问计数、平均值、最大值、最小值等。

    Edit2:如果您希望得到 long 的总和,请使用 summaryStatistics().getSum()

    Edit2:如果您特别希望访问数组数据的统计信息,您可以使用Arrays.stream​(int[] array, int startInclusive, int endExclusive),它会返回一个Instream也是。

    【讨论】:

    • @Andre 欢迎,对于sum 的长表示形式的编辑,您可以进一步使用统计API 和getSum
    • 我可以对 IntStream 说它应该有那个大小...如果你指的是数组的大小,无论如何你都在使用range(0, array.length) 做同样的事情跨度>
    • 要在一个数组范围内进行流式传输,您可以使用Arrays.stream(array, start, end),但正如我的回答中所说,无论如何您都不需要这个。
    • @Andre 使用 Arrays.stream(array, start, end),正如 Holger 已经指出的那样。
    • 为了完整起见,IntStream.range(from, to).map(ix -> array[ix]) 也可以,但 Arrays.stream(array, from, to) 是规范的。
    【解决方案3】:

    如果您真的想要使用流,那么利用跳过和限制:

    Arrays.stream(myArray).sorted().limit(4).sum();
    Arrays.stream(myArray).sorted().skip(1).limit(4).sum();
    

    这假设您已经有一个现有数组,并且只想在 java 中复制您的 Kotlin 代码。


    至于生成索引请查看IntStream.range

    例如

    IntStream.range(0, 4);
    

    03 返回一个IntStream,即4 是独占的,IntStream.rangeClosed(startInc, endInc) 可以生成从startIncendInc 的索引。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-27
      • 2021-04-16
      相关资源
      最近更新 更多