Java 求数组中的最小值和最大值

Java 求数组中的最小值和最大值,java,arrays,algorithm,Java,Arrays,Algorithm,这是一个非常基本的算法(无法变得更简单),但我被难倒了。我们有一个元素数组,我们必须确定最小值和最大值 通常的方法是遍历数组,找到最小值和最大值,即2n 稍微更有效的方法是首先成对比较数组的连续元素,以确定任意两个元素的最大值和最小值(n/2比较)。我们现在有n/2最小和n/2最大元素。现在我们可以得到n/2+n/2+n/2(上一步)=3/2*n或1.5n的最终最大值和最小值 那很好。从理论上讲,在第二种情况下,代码运行所需的时间应该更少,因为我们所做的比较更少。但是,当我运行代码时,结果是相反

这是一个非常基本的算法(无法变得更简单),但我被难倒了。我们有一个元素数组,我们必须确定最小值和最大值

通常的方法是遍历数组,找到最小值和最大值,即2n

稍微更有效的方法是首先成对比较数组的连续元素,以确定任意两个元素的最大值和最小值(n/2比较)。我们现在有n/2最小和n/2最大元素。现在我们可以得到n/2+n/2+n/2(上一步)=3/2*n或1.5n的最终最大值和最小值

那很好。从理论上讲,在第二种情况下,代码运行所需的时间应该更少,因为我们所做的比较更少。但是,当我运行代码时,结果是相反的

我的代码片段如下:

public class MinMax {
public static void nonEfficient(int [] array){
    int min=array[0],max=array[0];
    for (int anArray : array) {
        if (anArray < min)
            min = anArray;
        else {
            if (anArray > max)
                max = anArray;
        }
    }
    System.out.println("Max is :" + max);
    System.out.println("Min is :" + min);
}
public static void efficient(int [] arr,int length){
    int max,min;
    max = min = arr[0];
    int i = 0;
    for (; i < length / 2; i++)
    {
        int number1 = arr[i * 2];
        int number2 = arr[i * 2 + 1];
        if (arr[i * 2] >= arr[i * 2 + 1])
        {
            if (number1 > max)
                max = number1;
            if (number2 < min)
                min = number2;
        }
        else
        {
            if (number2 > max)
                max = number2;
            if (number1 < min)
                min = number1;
        }
    }
    if (i * 2 < length)
    {
        int num = arr[i * 2];
        if (num > max)
            max = num;
        if (num < min)
            min = num;
    }
    System.out.println("***********************");
    System.out.println("Max is :" + max);
    System.out.println("Min is :" + min);
}
public static void main(String[] args) {
    int [] array =  new int[10000000];
    Random rand = new Random();
    for(int i=0;i<array.length;i++)
        array[i] = rand.nextInt(100000)-144;
    long startTime = System.currentTimeMillis();
    nonEfficient(array); //theoretically non efficient 2n compares
    long stopTime = System.currentTimeMillis();
    long elapsedTime = stopTime - startTime;
    System.out.println(elapsedTime);// just 11ms

    startTime = System.currentTimeMillis();
    efficient(array, 10000000);///theoretically more efficient 1.5n compares
    stopTime = System.currentTimeMillis();
    elapsedTime = stopTime - startTime;
    System.out.println(elapsedTime);//whooping 37 ms..what happpened ????
}
}
公共类最小值{
公共静态无效无效(int[]数组){
int min=array[0],max=array[0];
for(整数数组:数组){
如果(数组<最小值)
最小值=无阵列;
否则{
如果(数组>最大值)
最大值=无阵列;
}
}
System.out.println(“最大值为:+Max”);
System.out.println(“最小值为:+Min”);
}
公共静态无效有效(int[]arr,int-length){
int max,min;
max=min=arr[0];
int i=0;
对于(;i=arr[i*2+1])
{
如果(编号1>最大值)
max=1号;
如果(数字2最大值)
max=数字2;
如果(1号<分钟)
最小=1号;
}
}
如果(i*2<长度)
{
int num=arr[i*2];
如果(数值>最大值)
max=num;
if(num对于(int i=0;i,我将使用JDK进行重载:

 Arrays.sort(array);   // sort from lowest to highest
 int min = array[0];   // the minimum is now the first element
 int max = array[array.length - 1];   // and the maximum is last

您可以在3行中完成。除非处理大型阵列,否则这将非常有效。

我将使用JDK来完成繁重的工作:

 Arrays.sort(array);   // sort from lowest to highest
 int min = array[0];   // the minimum is now the first element
 int max = array[array.length - 1];   // and the maximum is last

您可以在3行中完成。除非处理大型数组,否则这将非常有效。

您的函数
无效
不正确。如果使用
[5,4,3,2,1]调用它
,将永远不会执行
else
语句,并且
max
将设置为
Integer。最小值

您的函数
无效
不正确。如果使用
[5,4,3,2,1]调用它
,将永远不会执行
else
语句,
max
将设置为
Integer.MIN\u值

,让我们只计算比较:

for (int anArray : array) { // <- One: check array's border
    if (anArray < min)      // <- Two
        min = anArray;
    else {
        if (anArray > max)  // <- Three
            max = anArray;
    }
}
最后:
N/2*9=4.5N

或者,如果优化器足够好,它可以消除5,6,但我们有

N/2 * 7 = 3.5N
您可以稍微改进代码

int min = array[array.length - 1];
int max = min; // <- there's no need to call array[array.length - 1]

// You can start from array.length - 2 not from usual array.length - 1 here    
// Comparison with constant 0 is slightly better
// (one JZ or JNZ assembler instruction)
// than with array.length
for (int i = array.length - 2; i >= 0; --i) {
  int v = array[i];

  if (v > max)
    max = v;
  else if (v < min) 
    min = v;
}
int min=array[array.length-1];
int max=min;//让我们来计算比较:

for (int anArray : array) { // <- One: check array's border
    if (anArray < min)      // <- Two
        min = anArray;
    else {
        if (anArray > max)  // <- Three
            max = anArray;
    }
}
最后:
N/2*9=4.5N

或者,如果优化器足够好,它可以消除5,6,但我们有

N/2 * 7 = 3.5N
您可以稍微改进代码

int min = array[array.length - 1];
int max = min; // <- there's no need to call array[array.length - 1]

// You can start from array.length - 2 not from usual array.length - 1 here    
// Comparison with constant 0 is slightly better
// (one JZ or JNZ assembler instruction)
// than with array.length
for (int i = array.length - 2; i >= 0; --i) {
  int v = array[i];

  if (v > max)
    max = v;
  else if (v < min) 
    min = v;
}
int min=array[array.length-1];

int max=min;//如果您使用的是java8,那么可以采用流方法

在我看来,它在复杂的结构中更具可读性。
希望这对您有所帮助,如果您使用的是java8,您可以采用流方法

在我看来,它在复杂的结构中更具可读性。
希望这有助于在使用Java 8时,我不同意“不能变得更简单”这句话:

这段代码的性能不如您的,但考虑到您还获得了数组的计数和总数这一事实,它并没有那么差。这将您的代码与java8方法进行比较:

nonEfficient:
Max is :99855
Min is :-144
12
***********************
efficient:
Max is :99855
Min is :-144
43
***********************
java8:
Max is :99855
Min is :-144
69

在使用Java 8时,我不得不对“不能变得更简单”这句话持不同意见:

这段代码的性能不如您的,但考虑到您还获得了数组的计数和总数这一事实,它并没有那么差。这将您的代码与java8方法进行比较:

nonEfficient:
Max is :99855
Min is :-144
12
***********************
efficient:
Max is :99855
Min is :-144
43
***********************
java8:
Max is :99855
Min is :-144
69
试试这个:

if (length & 1)
{
  // Odd length, initialize with the first element
  min= max= a[0];
  i= 1;
}
else
{
  // Even length, initialize with the first pair
  if (a[0] < a[1])
  {
    min= a[0]; max= a[1];
  }
  else
  {
    min= a[1]; max= a[0];
  }
  i= 2;
}

// Remaining pairs
while (i < length)
{
    int p= a[i++], q= a[i++];
    if (p < q)
    {
      if (p < min) min= p;
      if (q > max) max= q;
    }
    else
    {
      if (q < min) min= q;
      if (p > max) max= p;
    }
}
if(长度&1)
{
//奇数长度,用第一个元素初始化
最小值=最大值=a[0];
i=1;
}
其他的
{
//偶数长度,使用第一对进行初始化
if(a[0]max)max=q;
}
其他的
{
如果(qmax)max=p;
}
}
您甚至可以使用这个丑陋的foreach循环摆脱数组索引,代价是布尔测试和额外的开销

// Initialize
min= max= a[0];

bool Even= true;
int p;
for (int q : a)
{
  if (Even)
  {
    // Set p on hold
    p= q;
  }
  else
  {
    // Process the pair
    if (p < q)
    {
      if (p < min) min= p;
      if (q > max) max= q;
    }
    else
    {
      if (q < min) min= q;
      if (p > max) max= p;
    }
  }
  Even= !Even;
}

if (!Even)
{
  // Process the last element
  p= a[length - 1];
  if (p < min) min= p;
  else 
    if (p > max) max= p;
}
//初始化
最小值=最大值=a[0];
布尔偶数=真;
INTP;
for(int q:a)
{
如果(偶数)
{
//让p暂停
p=q;
}
其他的
{
//处理这对
if(pmax)max=q;
}
其他的
{
如果(qmax)max=p;
}
}
偶数=!偶数;
}
如果(!偶数)
{
//处理最后一个元素
p=a[长度-1];
如果(pmax)max=p;
}
试试这个:

if (length & 1)
{
  // Odd length, initialize with the first element
  min= max= a[0];
  i= 1;
}
else
{
  // Even length, initialize with the first pair
  if (a[0] < a[1])
  {
    min= a[0]; max= a[1];
  }
  else
  {
    min= a[1]; max= a[0];
  }
  i= 2;
}

// Remaining pairs
while (i < length)
{
    int p= a[i++], q= a[i++];
    if (p < q)
    {
      if (p < min) min= p;
      if (q > max) max= q;
    }
    else
    {
      if (q < min) min= q;
      if (p > max) max= p;
    }
}
if(长度&1)
{
//奇数长度,用第一个元素初始化
最小值=最大值=a[0];
i=1;
}
其他的
{
//偶数长度,使用第一对进行初始化
if(a[0]max)max=q;
}
其他的
{
如果(qmax)max=p;
}
}
你甚至可以摆脱它