10个数组中最大的5个没有排序

时间:2015-09-04 10:19:33

标签: java algorithm

这是我的代码,用于查找数字数组中的最大数字,但我似乎无法理解如何获取前5个数字并将它们存储在数组中,然后检索它们

以下是代码:

public class Max {


    public static void main (String[] args) 
    {
        int i;
        int large[]=new int[5];     
        int array[] = {33,55,13,46,87,42,10,34,43,56};
        int max = array[0]; // Assume array[0] to be the max for time-being

        //Looping n-1 times, O(n)
        for(  i = 1; i < array.length; i++) // Iterate through the First Index and compare with max
        {
            // O(1)
            if( max < array[i])
            {
                // O(1)
                max = array[i];// Change max if condition is True
                large[i] = max;
            }
        }
        for (int j = 0; j<5; j++)
        {
            System.out.println("Largest 5 : "+large[j]);
        }
        System.out.println("Largest is: "+ max);
        // Time complexity being: O(n) * [O(1) + O(1)] = O(n)
    }

}

我正在使用一个数组存储5个数字,但是当我运行它时,它不是我想要的。 任何人都可以帮我解决这个问题吗?

10 个答案:

答案 0 :(得分:14)

从较大的集合中检索前n项的最佳数据结构是 min / max heap ,相关的抽象数据结构称为优先级队列。 Java有一个无限制的PriorityQueue,它基于堆结构,但没有专门用于基本类型的版本。它可以通过添加外部逻辑用作有界队列,有关详细信息,请参阅this comment

Apache Lucene有一个有界优先级队列的实现:

http://grepcode.com/file/repo1.maven.org/maven2/org.apache.lucene/lucene-core/5.2.0/org/apache/lucene/util/PriorityQueue.java#PriorityQueue

这是一个专门用于整理的简单修改:

/*
 * Original work Copyright 2014 The Apache Software Foundation
 * Modified work Copyright 2015 Marko Topolnik 
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/** A PriorityQueue maintains a partial ordering of its elements such that the
 * worst element can always be found in constant time.  Put()'s and pop()'s
 * require log(size) time.
 */
class IntPriorityQueue {
    private static int NO_ELEMENT = Integer.MIN_VALUE;
    private int size;
    private final int maxSize;
    private final int[] heap;

    IntPriorityQueue(int maxSize) {
        this.heap = new int[maxSize == 0 ? 2 : maxSize + 1];
        this.maxSize = maxSize;
    }

    private static boolean betterThan(int left, int right) {
        return left > right;
    }

    /**
     * Adds an int to a PriorityQueue in log(size) time.
     * It returns the object (if any) that was
     * dropped off the heap because it was full. This can be
     * the given parameter (in case it isn't better than the
     * full heap's minimum, and couldn't be added), or another
     * object that was previously the worst value in the
     * heap and now has been replaced by a better one, or null
     * if the queue wasn't yet full with maxSize elements.
     */
    public void consider(int element) {
        if (size < maxSize) {
            size++;
            heap[size] = element;
            upHeap();
        } else if (size > 0 && betterThan(element, heap[1])) {
            heap[1] = element;
            downHeap();
        }
    }

    public int head() {
        return size > 0 ? heap[1] : NO_ELEMENT;
    }

    /** Removes and returns the least element of the PriorityQueue in log(size)
     time. */
    public int pop() {
        if (size > 0) {
            int result = heap[1];
            heap[1] = heap[size];
            size--;
            downHeap();
            return result;
        } else {
            return NO_ELEMENT;
        }
    }

    public int size() {
        return size;
    }

    public void clear() {
        size = 0;
    }

    public boolean isEmpty() {
        return size == 0;
    }

    private void upHeap() {
        int i = size;
        // save bottom node
        int node = heap[i];
        int j = i >>> 1;
        while (j > 0 && betterThan(heap[j], node)) {
            // shift parents down
            heap[i] = heap[j];
            i = j;
            j >>>= 1;
        }
        // install saved node
        heap[i] = node;
    }

    private void downHeap() {
        int i = 1;
        // save top node
        int node = heap[i];
        // find worse child
        int j = i << 1;
        int k = j + 1;
        if (k <= size && betterThan(heap[j], heap[k])) {
            j = k;
        }
        while (j <= size && betterThan(node, heap[j])) {
            // shift up child
            heap[i] = heap[j];
            i = j;
            j = i << 1;
            k = j + 1;
            if (k <= size && betterThan(heap[j], heap[k])) {
                j = k;
            }
        }
        // install saved node
        heap[i] = node;
    }
}

您实现betterThan的方式决定它是表现为最小还是最大堆。这就是它的用法:

public int[] maxN(int[] input, int n) {
  final int[] output = new int[n];
  final IntPriorityQueue q = new IntPriorityQueue(output.length);
  for (int i : input) {
    q.consider(i);
  }
  // Extract items from heap in sort order
  for (int i = output.length - 1; i >= 0; i--) {
    output[i] = q.pop();
  }
  return output;
}

这种方法的表现与用户 rakeb.void 的简单线性扫描表达了一些兴趣。这些是与输入大小相关的结果size,总是在寻找16个顶级元素:

Benchmark             (size)  Mode  Cnt      Score      Error  Units
MeasureMinMax.heap        32  avgt    5    270.056 ±   37.948  ns/op
MeasureMinMax.heap        64  avgt    5    379.832 ±   44.703  ns/op
MeasureMinMax.heap       128  avgt    5    543.522 ±   52.970  ns/op
MeasureMinMax.heap      4096  avgt    5   4548.352 ±  208.768  ns/op
MeasureMinMax.linear      32  avgt    5    188.711 ±   27.085  ns/op
MeasureMinMax.linear      64  avgt    5    333.586 ±   18.955  ns/op
MeasureMinMax.linear     128  avgt    5    677.692 ±  163.470  ns/op
MeasureMinMax.linear    4096  avgt    5  18290.981 ± 5783.255  ns/op

结论:针对堆方法的常数因素非常低。盈亏平衡点大约是70-80个输入元素,从那时起,简单的方法就会急剧下降。请注意,常量因子源于按排序顺序提取项目的最终操作。如果不需要这样(即,只有 set 的最佳项目就足够了),我们可以直接检索内部heap数组并忽略heap[0]元素算法不使用。在这种情况下,即使对于最小的输入大小(我用32个中的4个顶部元素进行测试),这个解决方案也会像 rakib.void 那样胜出。

答案 1 :(得分:9)

请查看以下代码:

public static void main(String args[]) {
    int i;
    int large[] = new int[5];
    int array[] = { 33, 55, 13, 46, 87, 42, 10, 34, 43, 56 };
    int max = 0, index;
    for (int j = 0; j < 5; j++) {
        max = array[0];
        index = 0;
        for (i = 1; i < array.length; i++) {
            if (max < array[i]) {
                max = array[i];
                index = i;
            }
        }
        large[j] = max;
        array[index] = Integer.MIN_VALUE;

        System.out.println("Largest " + j +  " : " + large[j]);
    }
}

注意:如果您不想更改输入的数组,请复制它并对复制的数组执行相同的操作。

看看Integer.MIN_VALUE

我得到以下输出:

  

最大0:87

     

最大1:56

     

最大2:55

     

最大3:46

     

最大4:43

答案 2 :(得分:3)

这是一个简单的解决方案,我很快就被淘汰了

public class Main {
public static void main(String args[]) {
    int i;
    int large[] = new int[5];
    int array[] = { 33, 55, 13, 46, 87, 42, 10, 34, 43, 56 };

    for (int j = 0; j < array.length; j++) {
        for (i = 4; i >= 0; i--) {
            if (array[j] > large[i]) {
                if (i == 4) {
                    large[i] = array[j];
                }
                else{
                    int temp = large[i];
                    large[i] = array[j];
                    large[i+1] = temp;
                }
            }
        }
    }
    for (int j = 0; j<5; j++)
    {
        System.out.println("Largest "+ j + ":"+ large[j]);
    }
}

}

答案 3 :(得分:2)

排序,正则表达式,复杂的数据结构都很好,使编程变得简单。但是,我现在经常看到它们被滥用,没有人不得不怀疑:

即使计算机在过去几十年中变得<强>数千倍,感知性能仍然不仅不会增长,而且实际上减慢。一旦进入终端应用程序,即使在Windows 3.11或Windows 98或Gnome 1中,您也可以获得即时反馈,您通常会从您的计算机获得即时反馈。

但似乎越来越受欢迎的不仅是使用大锤来破解坚果,而且甚至是使用蒸汽锤的小麦玉米。

对于这么小的问题,你不需要friggin'排序或复杂的数据结构。不要让我调用Z̴̝̻̹̣̥͎A̞̭̞̩̠̝͢L̛̤̥͟͜G͘҉̯̯̼̺O̦͈͙̗͎͇̳̞̕͡。我不能接受它,即使我手头没有Java编译器,这里是我对C ++的看法(但也适用于Java)。

基本上,它将您的5个最大值初始化为可能的最小整数值。然后,它会浏览您的数字列表,对于每个数字,它会查找您的最大值以查看它是否有位置。

#include <vector>
#include <limits>    // for integer minimum
#include <iostream>  // for cout
using namespace std; // not my style, I just do so to increase readability

int main () {
    // basically, an array of length 5, initialized to the minimum integer
    vector<int> maxima(5, numeric_limits<int>::lowest());

    // your numbers
    vector<int> numbers = {33, 55, 13, 46, 87, 42, 10, 34, 43, 56};

    // go through all numbers.
    for(auto n : numbers) {

        // find smallest in maxima.
        auto smallestIndex = 0;
        for (auto m=0; m!=maxima.size(); ++m) {
            if (maxima[m] < maxima[smallestIndex]) {
                smallestIndex = m;
            }
        }

        // check if smallest is smaller than current number
        if (maxima[smallestIndex] < n)
            maxima[smallestIndex] = n;
    }

    cout << "maximum values:\n";
    for(auto m : maxima) {
        cout << " - " << m << '\n';
    }
}

它是rakeb.voids'答案的类似解决方案,但将内部翻转出来并且不必修改输入数组。

仅在适当时使用蒸汽锤。学习算法和数据结构。并知道何时不使用你的功夫。否则,你就会犯下不必要地增加社会浪费并导致整体瘫痪的罪行。

(Marko的Java翻译,适用于零分配的签名)

static int[] phresnel(int[] input, int[] output) {
  Arrays.fill(output, Integer.MIN_VALUE);
  for (int in : input) {
    int indexWithMin = 0;
    for (int i = 0; i < output.length; i++) {
      if (output[i] < output[indexWithMin]) {
        indexWithMin = i;
      }
    }
    if (output[indexWithMin] < in) {
      output[indexWithMin] = in;
    }
  }
  Arrays.sort(output);
  return output;
}

答案 4 :(得分:1)

作为排序的替代方案,这是逻辑。你找出了代码。

保留到目前为止找到的前X值的列表(或数组)。当然会开始是空的。

对于每个新值(迭代),请检查前X列表。

如果前X列表短于X,则添加值。

如果前X列表已满,请检查新值是否大于任何值。如果是,则从顶部X列表中删除最小值并添加新值。

提示:如果排名前X列表,代码会更好。

答案 5 :(得分:1)

首先,您不能将i常量与large数组一起使用。 i最多为10,而large长度为5。 为此使用单独的变量,并在添加新值时递增。

其次,此逻辑不检索最大值,您需要完全检查数组,检索最大值并将其添加到数组中。然后你又要了。您可以编写使用large.length作为条件的第一个循环和使用array.length的内循环。或者,您可以使用递归。

答案 6 :(得分:1)

如果您不想排序,可以检查较低的数字及其位置并进行更换。 WORKING DEMO HERE

public static void main(String[] args) {
    int array[] = {33,55,13,46,87,42,10,34,43,56};
    int mArray[] = new int[5];
    int j = 0;

    for(int i = 0; i < array.length; i++) {
        if (array[i] > lower(mArray)) {
            mArray[lowerPos(mArray)] = array[i];
        }
    }

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

public static int lower(int[] array) {
    int lower = Integer.MAX_VALUE;
    for (int n : array) {
        if (n < lower)
            lower = n;
    }
    return lower;
}

public static int lowerPos(int[] array) {
    int lower = Integer.MAX_VALUE;
    int lowerPos = 0;
    for (int n = 0; n < array.length; n++) {
        if (array[n] < lower) {
            lowerPos = n;
            lower = array[n];
        }
    }

    return lowerPos;
}

输出:

[43, 55, 56, 46, 87]

答案 7 :(得分:1)

这是另一种方法:

public static void main(String args[]){  

     int i;
     int largestSize = 4;
     int array[] = {33,55,13,46,87,42,10,34};
     // copy first 4 elemets, they can just be the highest 
     int large[]= Arrays.copyOf(array, largestSize);
     // get the smallest value of the large array before the first start
     int smallest = large[0];
     int smallestIndex = 0;
     for (int j = 1;j<large.length;++j) {
         if (smallest > large[j]) {
             smallest = large[j];
             smallestIndex = j;
         } 
     }
     // First Loop start one elemnt after the copy
     for(i = large.length; i < array.length; i++) 
     {
         // get the smallest value and index of the large array
         if(smallest  < array[i])
         {
             large[smallestIndex] = array[i];
             // check the next smallest value
             smallest = large[0];
             smallestIndex = 0;
             for (int j = 1;j<large.length;++j) {
                 if (smallest > large[j]) {
                     smallest = large[j];
                     smallestIndex = j;
                 } 
             }
         }
     }
     for (int j = 0; j<large.length; j++)
     {
         System.out.println("Largest 5 : "+large[j]);
     }
     System.out.println();
     System.out.println("Largest is: "+ getHighest(large));

}  

private static int getHighest(int[] array) {
    int highest = array[0];
    for (int i = 1;i<array.length;++i) {
        if (highest < array[i]) {
            highest = array[i];
        }
    }
    return highest;
}

答案 8 :(得分:1)

你可以用OOp方式正确地做到这一点。这将维护一个提供值列表的n个最大值的列表。

class Largest<T extends Comparable<T>> {

    // Largest so far - null if we haven't yet seen that many.
    List<T> largest;

    public Largest(int n) {
        // Build my list.
        largest = new ArrayList(n);
        // Clear it.
        for (int i = 0; i < n; i++) {
            largest.add(i, null);
        }
    }

    public void offer(T next) {
        // Where to put it - or -1 if nowhere.
        int place = -1;
        // Must replace only the smallest replaceable one.
        T smallest = null;
        for (int i = 0; i < largest.size(); i++) {
            // What's there?
            T l = largest.get(i);
            if (l == null) {
                // Always replace null.
                place = i;
                break;
            }
            if (l.compareTo(next) < 0) {
                // Only replace the smallest.
                if (smallest == null || l.compareTo(smallest) < 0) {
                    // Remember here but keep looking in case there is a null or a smaller.
                    smallest = l;
                    place = i;
                }
            }
        }
        if (place != -1) {
            // Replace it.
            largest.set(place, next);
        }
    }

    public List<T> get() {
        return largest;
    }
}

public void test() {
    Integer array[] = {33, 55, 13, 46, 87, 42, 10, 34, 43, 56};
    Largest<Integer> l = new Largest<>(5);
    for (int i : array) {
        l.offer(i);
    }
    List<Integer> largest = l.get();
    Collections.sort(largest);
    System.out.println(largest);
    // Check it.
    List<Integer> asList = Arrays.asList(array);
    Collections.sort(asList);
    asList = asList.subList(asList.size() - largest.size(), asList.size());
    System.out.println(asList);
}

对于较大的数字,您可以使用binarySearch来改进算法,以找到放置新项目的最佳位置,而不是盲目地走遍整个列表。这具有返回已排序列表的额外好处。

class Largest<T extends Comparable<T>> {

    // Largest so far - null if we haven't yet seen that many.
    List<T> largest;
    // Limit.
    final int n;

    public Largest(int n) {
        // Build my list.
        largest = new ArrayList(n + 1);
        this.n = n;
    }

    public void offer(T next) {
        // Try to find it in the list.
        int where = Collections.binarySearch(largest, next, Collections.reverseOrder());
        // Positive means found.
        if (where < 0) {
            // -1 means at start.
            int place = -where - 1;
            // Discard anything beyond n.
            if (place < n) {
                // Insert here.
                largest.add(place, next);
                // Trim if necessary.
                if (largest.size() > n) {
                    largest.remove(n);
                }
            }
        }
    }

    public List<T> get() {
        return largest;
    }
}

答案 9 :(得分:1)

尝试:

public static int  getMax(int max,int[] arr ){

         int pos=0;
           //Looping n-1 times, O(n)
            for( int i = 0; i < arr.length; i++) // Iterate through the First Index and compare with max
            {
                // O(1)
                if( max < arr[i])
                {
                    // O(1)
                     max = arr[i];// Change max if condition is True
                     pos=i;

                }
            }
            arr[pos]=0;

        return max;
    }




 public static void main(String[] args)  {

            int large[]=new int[10];     
            int array[] = {33,55,13,46,87,42,10,34,43,56};

            int k=0;
            for(int i=0;i<array.length;i++){
                large[k++]=getMax(0,array);

            }

            System.out.println("Largest 5 is: "+     Arrays.toString(Arrays.copyOf(large,5)));
}

输出:

Largest 5 is: [87, 56, 55, 46, 43]