【问题标题】:Finding the max/min value in an array of primitives using Java使用 Java 查找基元数组中的最大值/最小值
【发布时间】:2016-01-14 17:54:46
【问题描述】:

写一个函数来确定数组中的最小值/最大值很简单,例如:

/**
 * 
 * @param chars
 * @return the max value in the array of chars
 */
private static int maxValue(char[] chars) {
    int max = chars[0];
    for (int ktr = 0; ktr < chars.length; ktr++) {
        if (chars[ktr] > max) {
            max = chars[ktr];
        }
    }
    return max;
}

但这不是已经在某个地方完成了吗?

【问题讨论】:

标签: java arrays algorithm frameworks


【解决方案1】:

使用 Commons Lang(转换)+ Collections(最小/最大)

import java.util.Arrays;
import java.util.Collections;

import org.apache.commons.lang.ArrayUtils;

public class MinMaxValue {

    public static void main(String[] args) {
        char[] a = {'3', '5', '1', '4', '2'};

        List b = Arrays.asList(ArrayUtils.toObject(a));

        System.out.println(Collections.min(b));
        System.out.println(Collections.max(b));
   }
}

请注意,Arrays.asList() 包装了底层数组,因此它不应占用太多内存,也不应对数组元素执行复制。

【讨论】:

  • 什么是ArrayUtils
  • Arrays.asList() 应该没问题,但是ArrayUtils.toObject() 会将a 的每个元素复制到Character 的新数组中。
  • Arrays.asList(a) 不起作用。您不能列出原语(在这种情况下为List&lt;char&gt;)。首先,您需要将原始值转换为对象,这就是使用 ArrayUtils.toObject 的原因。
【解决方案2】:

您可以简单地使用新的 Java 8 Streams,但您必须使用 int

实用程序类Arraysstream 方法为您提供了一个IntStream,您可以在其上使用min 方法。你也可以max,sum,average,...

getAsInt方法用于从OptionalInt获取值

import java.util.Arrays;

public class Test {
    public static void main(String[] args){
        int[] tab = {12, 1, 21, 8};
        int min = Arrays.stream(tab).min().getAsInt();
        int max = Arrays.stream(tab).max().getAsInt();
        System.out.println("Min = " + min);
        System.out.println("Max = " + max)
    }

}

==UPDATE==

如果执行时间很重要,并且您只想遍历数据一次,您可以使用这样的summaryStatistics() 方法

import java.util.Arrays;
import java.util.IntSummaryStatistics;

public class SOTest {
    public static void main(String[] args){
        int[] tab = {12, 1, 21, 8};
        IntSummaryStatistics stat = Arrays.stream(tab).summaryStatistics();
        int min = stat.getMin();
        int max = stat.getMax();
        System.out.println("Min = " + min);
        System.out.println("Max = " + max);
    }
}

这种方法可以提供比经典循环更好的性能,因为 summaryStatistics 方法是 reduction operation 并且它允许并行化。

【讨论】:

    【解决方案3】:

    Google Guava library 在其 Chars、Ints、Longs 等类中具有 min 和 max 方法。

    所以你可以简单地使用:

    Chars.min(myarray)
    

    不需要任何转换,并且可以有效地实现。

    【讨论】:

    【解决方案4】:

    通过对数组进行排序,可以获得最小值/最大值的第一个和最后一个值。

    import java.util.Arrays;
    
    public class apples {
    
      public static void main(String[] args) {
        int a[] = {2,5,3,7,8};
        Arrays.sort(a);
    
        int min =a[0];
        System.out.println(min);
    
        int max= a[a.length-1];
        System.out.println(max);
      }
        
    }
    

    尽管排序操作比简单地通过简单的循环查找最小值/最大值更昂贵。但是当性能不是问题时(例如小型阵列,或者您的成本与您的应用程序无关),这是一个非常简单的解决方案。

    注意:在此之后数组也会被修改。

    【讨论】:

    • 我想这意味着如果你对数组进行排序(按升序),根据定义,最小值总是在第一个位置,a[0],最大值值将始终位于最后一个位置,[a.length-1]。
    • 这是解决问题的合法且有用的方法。与其他的相比,使用它有什么缺点?
    • @alex 时间复杂度 - 排序充其量是 O(nlogn) 的事情,而 Michael Rutherfurd 的方法是 O(n)。
    • 我们不需要排序,因为列表的单次迭代足以找到最小值和最大值。
    • @akhil_mittal 但这需要比排序更多的代码,因为没有 Java 标准方法来执行此迭代
    【解决方案5】:

    是的,它在Collections 类中完成。请注意,您需要手动将原始 char 数组转换为 Character[]。

    一个简短的演示:

    import java.util.*;
    
    public class Main {
    
        public static Character[] convert(char[] chars) {
            Character[] copy = new Character[chars.length];
            for(int i = 0; i < copy.length; i++) {
                copy[i] = Character.valueOf(chars[i]);
            }
            return copy;
        }
    
        public static void main(String[] args) {
            char[] a = {'3', '5', '1', '4', '2'};
            Character[] b = convert(a);
            System.out.println(Collections.max(Arrays.asList(b)));
        }
    }
    

    【讨论】:

    • Collections.min(myCollection);如果你想将它用于数组,你可以像 Collections.min(Arrays.asList(myArray));
    • char [] 转换为Character [] 只是为了确定最大值是非常低效的——最好为每个原始类型创建一个具有静态方法的实用程序类,类似于java.util.Arraysjava.sun.com/javase/6/docs/api/java/util/Arrays.html跨度>
    • @Christoph:是的,如果数组的大小很大,我会同意。如果所讨论的应用程序进行许多数据库调用和/或 I/O 操作并且数组的大小(相对)较小,那么简单地说它“效率低下”是没有意义的。
    • 出于性能原因,您应该使用Character.valueOf(chars[i]) 而不是new Character(chars[i])java.sun.com/javase/6/docs/api/java/lang/…
    • @Christoph Christoph 是对的,将数组转换为集合以进行最小最大搜索是低效且愚蠢的。
    【解决方案6】:

    我的所有应用程序中都有一个小助手类,其方法如下:

    public static double arrayMax(double[] arr) {
        double max = Double.NEGATIVE_INFINITY;
    
        for(double cur: arr)
            max = Math.max(max, cur);
    
        return max;
    }
    

    【讨论】:

    • 你应该使用 double max = Double.NEGATIVE_INFINITY;而不是 double max = Double.MIN_VALUE;因为双精度的 MIN_VALUE 是正数
    • ... 或者您可以将 max 设置为数组中的第一项,然后从第二项开始迭代,请参阅我的答案。
    【解决方案7】:

    您可以使用IntStreammax() 方法轻松完成。

    示例

    public static int maxValue(final int[] intArray) {
      return IntStream.range(0, intArray.length).map(i -> intArray[i]).max().getAsInt();
    }
    

    说明

    1. range(0, intArray.length) - 获取与intArray 中存在的元素一样多的流。

    2. map(i -&gt; intArray[i]) - 将流的每个元素映射到intArray 的实际元素。

    3. max() - 获取此流的最大元素为OptionalInt

    4. getAsInt() - 解开 OptionalInt。 (你也可以在这里使用:orElse(0),以防OptionalInt为空。)

    【讨论】:

      【解决方案8】:
          public int getMin(int[] values){
              int ret = values[0];
              for(int i = 1; i < values.length; i++)
                  ret = Math.min(ret,values[i]);
              return ret;
          }
      

      【讨论】:

      • 这是用于数字 int 但问题是要求原始值 int, long, char, byte....
      【解决方案9】:
      import java.util.Random;
      
      public class Main {
      
      public static void main(String[] args) {
         int a[] = new int [100];
         Random rnd = new Random ();
      
          for (int i = 0; i< a.length; i++) {
              a[i] = rnd.nextInt(99-0)+0;
              System.out.println(a[i]);
          }
      
          int max = 0;          
      
          for (int i = 0; i < a.length; i++) {
              a[i] = max;
      
      
              for (int j = i+1; j<a.length; j++) {
                  if (a[j] > max) {
                     max = a[j];
                  }
      
              }
          }
      
          System.out.println("Max element: " + max);
      }
      }
      

      【讨论】:

        【解决方案10】:

        reduce()的解决方案:

        int[] array = {23, 3, 56, 97, 42};
        // directly print out
        Arrays.stream(array).reduce((x, y) -> x > y ? x : y).ifPresent(System.out::println);
        
        // get the result as an int
        int res = Arrays.stream(array).reduce((x, y) -> x > y ? x : y).getAsInt();
        System.out.println(res);
        >>
        97
        97
        

        在上面的代码中,reduce()Optional 格式返回数据,您可以通过getAsInt() 将其转换为int

        如果要比较最大值和某个数,可以在reduce()中设置一个起始值:

        int[] array = {23, 3, 56, 97, 42};
        // e.g., compare with 100
        int max = Arrays.stream(array).reduce(100, (x, y) -> x > y ? x : y);
        System.out.println(max);
        >>
        100
        

        在上面的代码中,当reduce()以标识(起始值)作为第一个参数时,它返回的数据与标识的格式相同。有了这个属性,我们可以将这个解决方案应用到其他数组:

        double[] array = {23.1, 3, 56.6, 97, 42};
        double max = Arrays.stream(array).reduce(array[0], (x, y) -> x > y ? x : y);
        System.out.println(max);
        >>
        97.0
        

        【讨论】:

          【解决方案11】:

          这是一个实用程序类,为原始类型提供 min/max 方法:Primitives.java

          int [] numbers= {10,1,8,7,6,5,2};
              int a=Integer.MAX_VALUE;
              for(int c:numbers) {
                  a=c<a?c:a;
                  }
                  
              System.out.println("Lowest value is"+a);
          

          【讨论】:

            【解决方案12】:

            浮动示例:

            public static float getMaxFloat(float[] data) {
            
                float[] copy = Arrays.copyOf(data, data.length);
                Arrays.sort(copy);
                return copy[data.length - 1];
            }
            
            public static float getMinFloat(float[] data) {
            
                float[] copy = Arrays.copyOf(data, data.length);
                Arrays.sort(copy);
                return copy[0];
            }
            

            【讨论】:

            • 虽然您的解决方案可以工作,但它会将时间复杂度增加到 O(nlogn),而使用其他答案可以在 O(n) 中轻松找到 min。
            • 在这种情况下使用排序简直太疯狂了。
            • 当需要前 n>1 个最小/最大值并进行一些修复时,它会很有用。
            【解决方案13】:

            这是在大约 99% 的运行中获得最大值的解决方案(更改 0.01 以获得更好的结果):

            public static double getMax(double[] vals){
                final double[] max = {Double.NEGATIVE_INFINITY};
            
                IntStream.of(new Random().ints((int) Math.ceil(Math.log(0.01) / Math.log(1.0 - (1.0/vals.length))),0,vals.length).toArray())
                        .forEach(r -> max[0] = (max[0] < vals[r])? vals[r]: max[0]);
            
                return max[0];
            }
            

            (不完全严重)

            【讨论】:

            • ;-) 那是“不完全严重”好吧。犹豫要不要投票……
            【解决方案14】:

            将数组传递给使用 Arrays.sort() 对其进行排序的方法,因此它只对方法使用的数组进行排序,然后将 min 设置为 array[0] 并将 max 设置为array[array.length-1].

            【讨论】:

            • 可能值得注意的是,a) 这会修改数组,b) 对于大型数组,它是 O(nlog n) 而不是 O(n) 更昂贵的解决方案
            【解决方案15】:

            获取数组的最小值/最大值的基本方法。如果您需要未排序的数组,您可以创建一个副本或将其传递给返回最小值或最大值的方法。如果不是,排序数组会更好,因为它在某些情况下执行得更快。

            public class MinMaxValueOfArray {
                public static void main(String[] args) {
                    int[] A = {2, 4, 3, 5, 5};
                    Arrays.sort(A);
                    int min = A[0];
                    int max = A[A.length -1];
                    System.out.println("Min Value = " + min);        
                    System.out.println("Max Value = " + max);
                }
            }
            

            【讨论】:

            • 排序的问题在于它对于 O(n) 问题有 O(n log n) 开销。但这比已经给出的其他三个“对数组排序”的答案要好。
            【解决方案16】:
                int[] arr = {1, 2, 3};
            
                List<Integer> list = Arrays.stream(arr).boxed().collect(Collectors.toList());
                int max_ = Collections.max(list);
                int i;
                if (max_ > 0) {
                    for (i = 1; i < Collections.max(list); i++) {
                        if (!list.contains(i)) {
                            System.out.println(i);
                            break;
                        }
                    }
                    if(i==max_){
                        System.out.println(i+1);
                    }
                } else {
                    System.out.println("1");
                }
            }
            

            【讨论】:

              猜你喜欢
              • 2014-06-26
              • 1970-01-01
              • 2016-05-07
              • 2012-10-18
              • 2020-06-17
              • 2014-07-21
              • 2016-11-12
              • 2017-04-20
              相关资源
              最近更新 更多