2

I have a function that gets an array of primitive data (int), I need to return the array of two elements the smallest and the largest number. If length of the array is 1 then just return two first elements int the array. I came up with such solution:

public static int[] minMax(int[] arr) {
    if (arr.length==1)
        return new int[]{arr[0],arr[0]} ;// return if arr is 1 element
    else {
        ArrayList<Integer> ar = new ArrayList<Integer>();
        //?
        return new int[]{Collections.max(ar),Collections.min(ar)};
    }
}

But how do I convert an array to an ArrayList? Is there a more efficient way maybe?

5
  • I know I can add elemts to the end of the list using for and itterating every element of the arr[] but this is probably going to be time consuming and not the best approah Commented Jul 18, 2022 at 9:58
  • IntStream.of(arr).boxed().collect(Collectors.toList()) Commented Jul 18, 2022 at 9:58
  • "I know I can add elemts to the end of the list using for and itterating every element" There is no way to do this in less than O(n). Every approach is going to involve iterating all the items. Commented Jul 18, 2022 at 9:59
  • so then that was a stupid question, sorry Commented Jul 18, 2022 at 10:03
  • what if the array is empty the return also will be empty or null? Commented Jul 18, 2022 at 11:10

3 Answers 3

3

By calling Collections.min and Collections.max, you're iterating over the array twice. You can cut this time down by streaming the array and letting it do the heavy lifting, as James Mudd suggested. However, note that by doing so you'd be wasting time on calculating the sum and accumulating the count of the elements, which you don't care about. It may be more efficient to calculated these yourself:

public static int[] minMax(int[] arr) {
    // Assuming arr has at least one element
    int min = arr[0];
    int max = arr[0];
    for (int i = 1; i < arr.length; ++i) {
        int curr = arr[i];
        if (curr < min) {
            min = curr;
        } else if (curr > max) {
            max = curr;
        }
    }
    return new int[]{min, max};
}
Sign up to request clarification or add additional context in comments.

Comments

2

You could use IntSummaryStatistics the method would look like

public static int[] minMax(int[] arr) {
    IntSummaryStatistics intSummaryStatistics = Arrays.stream(arr).summaryStatistics();
    return new int[] {intSummaryStatistics.getMin(), intSummaryStatistics.getMax()};
}

Comments

0

Here's another way of solving this task with streams.

Instead, using IntSummuryStatistics we can provide an array of two elements as a container of the resulting values while applying collect and manually define to accumulate stream elements in it.

public static int[] minMax(int[] sourceArr) {
    
    if (sourceArr.length == 0) throw new IllegalArgumentException(); // source array is empty
    
    return Arrays.stream(sourceArr)
        .collect(
            () -> new int[]{sourceArr[0], sourceArr[0]}, // mutable container
            (arr, next) -> {                             // accumulator - populating the container with elements of the stream
                arr[0] = Math.min(arr[0], next);
                arr[1] = Math.max(arr[1], next);
            },
            (left, right) -> {                           // combiner - merging containers in parallel
                left[0] = Math.min(left[0], right[0]);
                left[1] = Math.max(left[1], right[1]);
            });
}

main()

public static int[] minMax(int[] sourceArr) {
    System.out.println(Arrays.toString(minMax(new int[]{3, 5, -3, 8, 9})));
    System.out.println(Arrays.toString(minMax(new int[]{3, -1, 3, 12, 27})));
}

Output:

[-3, 9]
[-1, 27]

But how do I convert an array to an ArrayList?

It's not possible to convert an array of primitives into a List directly. When you have an array of reference type (like Integer, BigDecimal, etc.) you can use Arrays.asList() to fixed-size list wrapped around the given array. But it wouldn't work with primitive arrays.

In order to translate int[] into a List<Integer> you have to create a new list and populate it with the contents of the array.

So your actual goal is to obtain the result as a list, the code provided above might be changed like that:

public static List<Integer> minMax(int[] sourceArr) {
    
    if (sourceArr.length == 0) throw new IllegalArgumentException(); // source array is empty
    
    return Arrays.stream(sourceArr)
        .collect(
            () -> Arrays.asList(sourceArr[0], sourceArr[0]), // mutable container
            (list, next) -> {                             // accumulator - populating the container with elements of the stream
                list.set(0, Math.min(list.get(0), next));
                list.set(1, Math.max(list.get(1), next));
            },
            (left, right) -> {                           // combiner - merging containers in parallel
                left.set(0, Math.min(left.get(0), right.get(0)));
                left.set(1, Math.max(left.get(1), right.get(1)));
            });
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.