Sandeep Tiwari
Sandeep Tiwari

Reputation: 2072

Find second min element from array

Anyone can convert this in the Java functional style (lambda):

public int findSecondMin(int arr[]) {

    int min = Integer.MAX_VALUE, secondMin = Integer.MAX_VALUE;
    for (int i = 0; i < arr.length; i++) {
        if (min > arr[i]) {
            secondMin = min;
            min = arr[i];
        } else if (secondMin > arr[i]) {
            secondMin = arr[i];
        }
    }
    return secondMin;
}

I tried by applying the filter over this but it is not working.

Upvotes: 2

Views: 2386

Answers (5)

malith vitha
malith vitha

Reputation: 493

public int min(){
  int a[] ={2,5,1,3};
  int min, secondMin = a[0];
  for(int i=0;i<a.length;i++){
        if(min>a[i]){
             secondMin =min;
             min= a[i];
           }
      }
  return secondMin;
}

i got the second min from above code segment...try this.....

Upvotes: 0

Nikolas
Nikolas

Reputation: 44446

There is a way even without sorting working in the case all the numbers are unique. Filter out the minimum value and ask again for another one resulting in the 2nd lowest value.

int firstMin = Arrays.stream(arr).min().getAsInt();
int secondMin = Arrays.stream(arr).filter(i -> i != firstMin).min().getAsInt();

System.out.println(firstMin);  // prints 2
System.out.println(secondMin); // prints 3

Edit: There is another way using the TreeSet implementation which stores already sorted values. Remove the lowest one and ask for the first element again - it results in the 2nd lowest element:

SortedSet<Integer> sortedSet = Arrays.stream(arr)
                                     .boxed()
                                     .collect(Collectors
                                         .toCollection(TreeSet::new));
sortedSet.remove(sortedSet.first());
int secondMin = sortedSet.first();

System.out.println(secondMin); // prints 3

Upvotes: 3

piradian
piradian

Reputation: 444

EDIT: As mentioned in comments - below solution will NOT work for parallel processing!

To avoid sorting we can use reduce function. And reduce to "pair like structure" (in the example imitated by array):

public class Test {

    private static final int SECOND_LOWEST = 1;
    private static final int LOWEST = 0;
    @Test
    public void test() {
        Integer[] arr = {0, 3, 4, 5, 2, 3, 5, 6, 7, 8, 1};
        List<Integer> list = Arrays.asList(arr);
        int[] identity = {Integer.MAX_VALUE, Integer.MAX_VALUE};
        int[] result = list.stream()
                       .reduce(identity, (acc, elem) -> calculate(acc, elem), (acc1, acc2) -> acc1);

       System.out.println(Arrays.toString(result));
    }

    private int[] calculate(int[] acc, Integer elem) {
        if (acc[LOWEST] > elem) {
            int prevLowest = acc[LOWEST];
            acc[LOWEST] = elem;
            acc[SECOND_LOWEST] = prevLowest;
        } else if (acc[SECOND_LOWEST] > elem) {
                acc[SECOND_LOWEST] = elem;            
    }
    return acc;
}

Upvotes: 0

Malte Hartwig
Malte Hartwig

Reputation: 4555

Using an IntStream, you can easily sort it and skip the first element:

public int findSecondMin(int[] arr)
{
    return IntStream.of(arr).sorted().skip(1).findFirst().orElse(Integer.MAX_VALUE);
}

But of course, you don't have to use streams. java.util.Arrays has a nice sort method, and then you can just take the second element:

public int findSecondMin(int[] arr)
{
    Arrays.sort(arr);
    return arr.length < 2 ? Integer.MAX_VALUE : arr[1];
}

To avoid sorting the whole array, we can take your approach and adapt it into a custom reduction on the stream:

public int findSecondMin(int[] arr)
{
    return IntStream.of(arr).boxed().reduce(
        new int[] {Integer.MAX_VALUE, Integer.MAX_VALUE},
        (mins, i) -> {
            return new int[] {Math.min(i, mins[0]), Math.min(Math.max(i, mins[0]), mins[1])};
        }, (mins1, mins2) -> {
            int[] lesser = mins1[0] < mins2[0] ? mins1 : mins2;
            int[] larger = mins1[0] < mins2[0] ? mins2 : mins1;
            return new int[] {lesser[0], Math.min(lesser[1], larger[0])};
        }
    )[1];
}

Compared to a for loop based implementation, it might be harder to read, but can work in parallel.

Upvotes: 4

Faiz Akram
Faiz Akram

Reputation: 558

here you find the Example

    List<Integer> numbers = Arrays.asList(10, 2, 3, 4, 5, 6);
            numbers.sort(Comparator.naturalOrder());
            System.out.println(numbers.get(1));

Upvotes: 0

Related Questions