簡體   English   中英

使用 Java 8 流從整數列表中計算最小和最大和

[英]Calculating Min and Max sums from a List of Integer using Java 8 streams

我正在嘗試解決以下挑戰:

給定五個正整數,找出可以通過將五個整數中的四個恰好相加來計算的最小值和最大值。 然后將各自的最小值最大值打印為單行的兩個空格分隔long整數。

下面可以看到我的代碼能夠處理一些測試用例,但其他一些我似乎無法弄清楚的失敗,問題似乎在於long max賦值語句,並且可能與.sorted(Collections.reverseOrder())組件,因為這是 min 與 max 語句之間的唯一明顯區別。

有效的示例測試用例:

Input = [1, 2, 3, 4, 5]

Output = 10 (minimum), 14 (maximum)

不起作用的示例測試用例:

Input = [256741038, 623958417, 
   467905213, 714532089, 938071625]

Output = 2063136757 (minimum), 
  -1550499952 (maximum)

Expected Output = 2063136757 
  (minimum), 2744467344 (maximum)

我的代碼:

class Result {
    
    /*
     * Complete the 'miniMaxSum' function below.
     *
     * The function accepts. INTEGER_ARRAY arr as parameter.
     */
    
    public static void miniMaxSum(List<Integer> arr) {
        long max = arr.stream().sorted(Collections.reverseOrder())
                .limit(4)
                .reduce(0, (subtotal, element) -> subtotal + element);
        long min = arr.stream().sorted().limit(4).reduce(0,
                (subtotal, element) -> subtotal + element);
        System.out.println(min + " " + max);
    }
}

public class Solution {
    public static void main(String[] args) throws IOException {
        BufferedReader bufferedReader =
                new BufferedReader(new InputStreamReader(System.in));
        
        List<Integer> arr = Stream
                .of(bufferedReader.readLine().replaceAll("\\s+$", "")
                        .split(" "))
                .map(Integer::parseInt).collect(toList());
        
        Result.miniMaxSum(arr);
        
        bufferedReader.close();
    }
}

正如@Benjamin W. 所說,這里似乎發生了一些溢出。 它可能與包含 Integer 對象而不是 long 的列表有關,但您必須進一步研究它。 你的緩沖閱讀器看起來工作得很好。

如果你只是想要一個簡單的解決方案,你可以在列表中找到最小的數字,從最大的和中省略它,從列表中找到最大的元素,從最小的和中省略它。

public static void minmaxSum(List<Integer> arr) {
    if (arr.size() == 0) return;

    long max = arr.get(0):
    long min = arr.get(0);

    long maxSum = 0;
    long minSum = 0;

    for (Integer num : arr) {
        long longNum = (long) num.intValue();
        
        maxSum += longNum;
        minSum += longNum;

        if (longNum < min) min = longNum;
        if (longNum > max) max = longNum;
    }

    maxSum -= min;
    minSum -= max;

    System.out.println(minSum + " " + maxSum);
}       

此外,這樣的代碼無論如何都要清晰得多。

Math.addExact

正如ShinyMustard22 的答案中所解釋的,您似乎遇到了溢出整數類型限制的問題。

發生溢出而沒有警告您。 如果您想在發生溢出時得到通知,並且您應該希望這樣做,請使用Math類中的…Exact方法。 如果在操作過程中發生溢出,則拋出異常。 您捕獲該異常,以您選擇的方式解決情況。

例如, Math.addExact( long x , long y )

發生溢出是因為您正在對Integer流執行歸約,即reduce()操作的累加器處理Interger對象,然后將計算的溢出結果分配給long類型的變量。

LongSummaryStatistics & LongStream

由於在兩種情況下都應該丟棄一個值(對於minmax sum ),我們可以通過計算所有元素的總和並減去最低元素的值以獲得最大和並減去最高元素的值來解決這個問題元素來獲得最小總和

無需在流中應用排序和硬編碼4的值。 如果您不想養成壞習慣,請嘗試將您的解決方案設計為干凈且通用的。

我們可以通過對給定列表執行單次迭代來獲得所有三個值(總計最低元素最高元素)。 它可以通過在使用for循環迭代時跟蹤這些值來“手動”完成,或者我們可以使用 JDK 中的一個匯總統計類來為我們完成這項工作。

匯總統計對象中,我們可以使用其方法getSum() 、 getMin() 和getMax()提取有關總和、最小值和最大值的信息。 為了避免int溢出,我們必須使用LongSummaryStatistics 我們可以通過將summaryStatistics()作為終端操作從LongStream中獲取該對象。

public static void miniMaxSum(List<Integer> arr) {
    LongSummaryStatistics statistics = arr.stream()
        .mapToLong(i -> i)
        .summaryStatistics();
    
    long max = statistics.getSum() - statistics.getMin();
    long min = statistics.getSum() - statistics.getMax();
    
    System.out.println(min + " " + max);
}

main()

public static void main(String[] args) {
    miniMaxSum(List.of(256741038, 623958417, 467905213, 714532089, 938071625));
}

輸出:

2063136757 2744467344

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM