从数组中查找第二个min元素

时间:2018-08-06 10:01:20

标签: java arrays lambda java-8 java-stream

任何人都可以将其转换为Java函数样式(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;
}

我尝试对此应用过滤器,但是它不起作用。

5 个答案:

答案 0 :(得分:4)

使用IntStream,您可以轻松对其进行排序并跳过第一个元素:

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

但是,当然,您不必使用流。 java.util.Arrays有一个很好的排序方法,然后您可以采用第二个元素:

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

为避免对整个数组进行排序,我们可以采用您的方法并将其调整为流中的自定义缩减:

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];
}

与基于for循环的实现相比,它可能更难阅读,但可以并行工作。

答案 1 :(得分:2)

在所有数字都是唯一的情况下,即使不进行排序,也存在一种方法。滤出最小值,然后再次要求获得最小值,从而得出第二低的值。

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

编辑:使用TreeSet实现的另一种方式是存储已排序的值。删除最低的元素,然后再次询问第一个元素-它导致第二个最低的元素:

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

答案 2 :(得分:0)

在这里找到示例

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

答案 3 :(得分:0)

编辑:  如评论中所述-以下解决方案不适用于并行处理!

为避免排序,我们可以使用reduce函数。并简化为“成对结构”(在数组模仿的示例中):

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;
}

答案 4 :(得分:0)

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;
}

我从上面的代码段中获得了第二分钟...尝试这个.....