11

Here's my code to find the max number in an array of numbers, but i can't seem to understand how to get the top 5 numbers and store them in an array and later retrieve them

Here's the code:

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

}

I'm using an array to store 5 numbers, but when i run it, it is not what i want. Can anyone help me with the program?

Bor
  • 775
  • 3
  • 19
  • 44
bappi bazzi
  • 225
  • 1
  • 3
  • 12

11 Answers11

14

The optimum data structure to retrieve top n items from a larger collection is the min/max heap and the related abstract data structure is called the priority queue. Java has an unbounded PriorityQueue which is based on the heap structure, but there is no version specialized for primitive types. It can used as a bounded queue by adding external logic, see this comment for details..

Apache Lucene has an implementation of the bounded priority queue:

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

Here is a simple modification that specializes it for ints:

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

The way you implement betterThan decides whether it will behave as a min or max heap. This is how it's used:

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

Some interest was expressed in the performance of this approach vs. the simple linear scan from user rakeb.void. These are the results, size pertaining to the input size, always looking for 16 top elements:

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

Conclusion: constant factors working against the heap approach are quite low. The breakeven point is around 70-80 input elements and from then on the simple approach loses steeply. Note that the constant factor stems from the final operation of extracting items in sort order. If this is not needed (i.e., just a set of the best items is enough), the we can simply retrieve the internal heap array directly and ignore the heap[0] element which is not used by the algorithm. In that case this solution beats one like rakib.void's even for the smallest input size (I tested with 4 top elements out of 32).

Community
  • 1
  • 1
Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
  • so how do i store them then? – bappi bazzi Sep 04 '15 at 10:30
  • Put them all into the queue, checking queue size at each step. If size exceeds n, remove the first element. In the end the queue will contain your top n elements. – Marko Topolnik Sep 04 '15 at 10:30
  • From the docs of `PriorityQueue`: `The elements of the priority queue are ordered according to their natural ordering, or by a Comparator provided at queue construction time,` . So in the end, they are going to be ordered. – Fran Montero Sep 04 '15 at 10:31
  • @FranMontero Heap is not a binary search tree. The items are not fully sorted, but can be removed one by one in sort order. – Marko Topolnik Sep 04 '15 at 10:32
  • 1
    correct me if i'm wrong, if i perform sorting it increases the time complexity, so storing in an priority queue is a better option or sorting with respect to the time complexity – bappi bazzi Sep 04 '15 at 10:34
  • Exactly, a max heap structure will not sort the whole input array. It will do the minimum work needed to maintain the top _n_ elements. It will be linear in the size of input and logarithmic in _n_. – Marko Topolnik Sep 04 '15 at 10:35
  • can you suggest how to achieve that – bappi bazzi Sep 04 '15 at 10:37
  • This is the best answer IMO - you can "heapify" all the data in O(n) and then its O(logn) to pop an element of the queue - which is probably the best performance you will get for the problem – rhinds Sep 04 '15 at 10:37
  • Refer to this post for details: http://stackoverflow.com/questions/7878026/is-there-a-priorityqueue-implementation-with-fixed-capacity-and-custom-comparato#comment9641001_7878089 – Marko Topolnik Sep 04 '15 at 10:38
  • I am really not sure if a tree data structure is the optimum for small inputs. In Big O notation, probably, but in cold facts, probably not. – Sebastian Mach Sep 04 '15 at 15:46
  • @phresnel Have you looked at the implementation? It's an array which is never expanded. It will fit into a cache line or two. – Marko Topolnik Sep 04 '15 at 15:49
  • @MarkoTopolnik: Yes, it will probably not even fill a whole cacheline. Yet there's some datastructures and traversal involved. I am not saying it's not fast, but "optimal" is a very provocative construct, a claim of perfectness. What about the predictibility of your algorithm? Does it play nice with branch prediction, especially when looping over bit-modified variables? A comparison of performance with a flat maximiser would be interesting. My bet would be on the flat ones, there, the whole code is almost guaranteed to be cached and predictable. – Sebastian Mach Sep 04 '15 at 16:07
  • For starters I would like to understand what you're saying. What do you mean by "looping over bit-modified variables" and what's the flat maximizer? – Marko Topolnik Sep 04 '15 at 17:09
  • @Marko What I think he's trying to say is that for say getting the top 5 elements of a 20 list element a simple algorithm based on selection sort which runs in O(nk) will beat this one. I'd say he's probably right, but then we're talking about ns of runtime, so neither one matters much I'd say. The usual big constant factor outweighs asymptotic growth (i.e. why nobody uses karatsuba for multiplying 128bit numbers) – Voo Sep 04 '15 at 17:23
  • @voo yes, I already commented to that effect under the answer which proposes n linear scans. But that's just not the way to make it interesting or have wider relevance. – Marko Topolnik Sep 04 '15 at 17:26
  • @MarkoTopolnik: I don't see when you answer without `@phresnel` :) What I mean by those: 1) you loop over j with j >>>= 1; inside the body. Not every compiler can optimize this good enough such that the loop can be run speculative nicely. Also, you have many different loop dependencies and many loops, branch target buffers do not like it very much. But that's a matter of measuring with a profiler. 2) "Flat Maximiser": Flat in contrast to tree algorithms and datastructures; e.g. I just have flat loops, which is nice for BTBs, caching, speculative execution. "Maximiser" -> maximizing algorithms. – Sebastian Mach Sep 05 '15 at 06:08
  • @phresnel Sorry, I was at a mobile phone and i forgot the mention. The loop condition is based on the value loaded from the array: that's all the predictability showstopper you need :) But there aren't many loops, just one. That one is complex and has two branches per step. It trades that for the ability to run just log(n) times and my measurements prove it's a good tradeoff. But I still don't know specifically how a flat maximizer wood look. Do you have in mind something like the "curtailed selection sort" presented by _rakeb.void_? Linear search? – Marko Topolnik Sep 05 '15 at 06:17
  • @MarkoTopolnik: Yes, something like rakeb's solution; or simply mine :) As mentioned, I would be happy to see a thorough comparison of our solutions (and rakeb's; my solution is very similar to rakeb's, but flips the loops); I am really just speculating that rakeb's/my solution is faster. – Sebastian Mach Sep 05 '15 at 06:21
10

Look at the following code:

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

Note: If you don't want to change the inputted array, then make a copy of it and do the same operation on the copied array.

Take a look at Integer.MIN_VALUE.

I get the following output:

Largest 0 : 87

Largest 1 : 56

Largest 2 : 55

Largest 3 : 46

Largest 4 : 43

Community
  • 1
  • 1
mazhar islam
  • 5,561
  • 3
  • 20
  • 41
  • hey, what's the time complexity for this program – bappi bazzi Sep 04 '15 at 10:41
  • @bappibazzi, I used your code for finding the max, then replaced it with MIN value, so that it wont come again. – mazhar islam Sep 04 '15 at 10:42
  • 2
    @bappibazzi he is getting the maximum value of the array 5 times, and after getting it he sets the value in the original array to the lowest value possible `Integer.Min_Value`. as a result the max value isn´t present anymore in the array – SomeJavaGuy Sep 04 '15 at 10:43
  • i'm still unclear what's the use of Integer.Min_Value – bappi bazzi Sep 04 '15 at 10:49
  • Of course, it destroys the initial array, which may not be allowed. – Andreas Sep 04 '15 at 10:50
  • 4
    This is _O(m n)_ where _m_ is input size and _n_ is in your case five. For small inputs this is enough. – Marko Topolnik Sep 04 '15 at 10:51
  • @First we find the max number, and its index. Then we replace that max value with the least possible integer we have, which is `Integer.MIN_VALUE`. So next time that max will never come again. – mazhar islam Sep 04 '15 at 10:51
  • 1
    Asking for top 5 of { 33, 55, 13 } will return { 33, 55, 13, MIN_VALUE, MIN_VALUE }. Not necessarily what you want, but asking for top 5 of 3 values is weird to begin with. – Andreas Sep 04 '15 at 11:18
  • As [Marko](https://stackoverflow.com/questions/32395648/largest-5-in-array-of-10-numbers-without-sorting#comment52660932_32395987) says, this solution is horrible in terms on time complexity - it will be untenable for large input arrays. – Boris the Spider Sep 04 '15 at 16:51
  • 1
    @BoristheSpider, You may find the in the comment section that I asked any other restriction does OP has to solve this problem, he said none. So I provide the simple solution with `O(m*n)`. – mazhar islam Sep 04 '15 at 17:36
  • 1
    This has a bug: once the first element is the max one, you never reassign `index` so the same number keeps repeating. – Marko Topolnik Sep 04 '15 at 18:53
  • @MarkoTopolnik: yes, I tried it and I always get the same number repeating.. I also checked a link you wrote (ideone.com/MyLFMU), but I could not find the difference with this one.. could u please help? – mOna Dec 09 '15 at 14:10
3

Here is a simple solution i quickly knocked up

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

}

2

Sorting, regular expressions, complex data structures are fine and make programming easy. However, I constantly see them misused nowadays and no one has to wonder:

Even if computers have become thousands of times faster over the past decades, the perceived performance still continues to not only not grow, but actually slows down. Once in your terminal application, you had instant feedback, even in Windows 3.11 or Windows 98 or Gnome 1, you often had instant feedback from your machine.

But it seems that it becomes increasingly popular to not only crack nuts with a sledgehammer, but even corns of wheat with steam hammers.

You don't need no friggin' sorting or complex datastructures for such a small problem. Don't let me invoke Z̴̲̝̻̹̣̥͎̀A̞̭̞̩̠̝̲͢L̛̤̥̲͟͜G͘҉̯̯̼̺O̦͈͙̗͎͇̳̞̕͡. I cannot take it, and even if I don't have a Java compiler at hands, here's my take in C++ (but will work in Java, too).

Basically, it initializes your 5 maxima to the lowest possible integer values. Then, it goes through your list of numbers, and for each number, it looks up into your maxima to see if it has a place there.

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

It is a similar solution to rakeb.voids' answer, but flips the loops inside out and does not have to modify the input array.

Use steam hammers when appropriate only. Learn algorithms and datastructures. And know when NOT TO USE YOUR KUNG-FU. Otherwise, you are guilty of increasing the society's waste unecessarily and contribute to overall crapness.


(Java translation by Marko, signature adapted to zero allocation)

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;
}
Community
  • 1
  • 1
Sebastian Mach
  • 38,570
  • 8
  • 95
  • 130
  • ... one reason why I am embittered: I do a lot of JavaScript coding recently, and I could puke on how many problems are hammered down by regexes where totally inappriate. Replacing all `<`, `[`, `.`, `?`? Use four regex-replaces on a multi kilobyte string seems the appropriate solution in JavaScript. – Sebastian Mach Sep 04 '15 at 16:04
  • The advantage of this over rakib's should be not thrashing the cache lines by repeatedly going through the large array. I expect this to beat the heap-based solution for any input size, as long as the number of maxima is low enough. – Marko Topolnik Sep 05 '15 at 06:30
  • @MarkoTopolnik: That's for sure. For larger lists of maxima (is that even right? Is "maximums" more correct?), more complex algorithms grow friendlier. – Sebastian Mach Sep 05 '15 at 06:37
  • Let's see where the breakeven point is, though... BTW to be identical to other solutions, you should also sort the maxima array. – Marko Topolnik Sep 05 '15 at 06:38
  • I translated your code to Java and posted into your answer at the bottom, check it out. Unfortunately, JMH says it very slow, about 3x worse than rakib. – Marko Topolnik Sep 05 '15 at 07:00
  • @MarkoTopolnik: That's pretty interesting. One would have to equalize them some more I guess, and then warm them up a bit to see what the VM optimizer comes up with (I once wrote an image-transformer that only worked nice after like 10 runs, starting at 6 seconds per bunch, ending at 0.5 seconds after a few runs). Some allocations might also be faster in C++ -- Regarding sorting the array: I don't think this is part of the problem. Actually, we C++ folk even have some specialized sorting function like nth_element, which leaves anything unsorted, except that the n largest elements are on the .. – Sebastian Mach Sep 07 '15 at 08:03
  • This is measured on the industry-standard measurement harness, JMH. I don't even start measuring for the first two seconds of runtime. I adapted the code to zero allocation, but allocation throughput is very high on HotSpot. Without sorting your code is still behind by a linear factor (sorting is a constant factor wrt. input size), and my code without sorting beats rakib even on smallest input. – Marko Topolnik Sep 07 '15 at 08:19
  • @MarkoTopolnik: Interesting. Wrt optimization, my homestead is more of the C and C++ sort of languages, where you basically have maximum control on pretty much everything, and where writing a reliable benchmark is something that only old shots should do. I cannot really argue in Java (would I do Java in a project, I would lift myself to a level were I could), but I think we agree that sorting a whole list just for the purpose of getting a subset thereof is evil :) – Sebastian Mach Sep 07 '15 at 08:36
  • But the _output_ would be usually expected to be sorted. BTW I wrote some optimized C code for the LZ4 decompressor, the amount of control was less than I had in Java with Unsafe. It was about aligned memory access. – Marko Topolnik Sep 07 '15 at 08:37
  • @MarkoTopolnik: I think it depends. If it's "Top 10 NASCAR drivers of all time", then yes, it should be sorted. But if you just need the "Nearest 7 Enemies" in a video game for homing missile simulation, it does not have to be. -- The most relevant C++ compilers have language extensions for memory layout and alignment, and since C++11 `alignas`. Then, you have more control about where to store your object (stack vs heap, or even memory maps) and about its lifetime (RAII exploits this) and whether to destroy at all or just leave behind on stack. Not always a good thing, but sometimes, it is. – Sebastian Mach Sep 07 '15 at 08:52
1

As an alternative to sorting, here is the logic. You figure out the code.

Keep a list (or array) of the top X values found so far. Will of course start out empty.

For each new value (iteration), check against top X list.

If top X list is shorter than X, add value.

If top X list is full, check if new value is greater than any value. If it is, remove smallest value from top X list and add new value.

Hint: Code will be better if top X list is sorted.

Andreas
  • 154,647
  • 11
  • 152
  • 247
1

First of all, you can't use the i constant with large array. i goes up to 10, while large length is 5. Use a separate variable for that and increment when you add a new value.

Second, this logic is not retrieving the max values, you need to go over your array fully, retrieve the max value and add it to your array. Then you have to it again. You can write a first loop which use large.length as a condition and the inner loop which will use array.length. Or, you can use recursion.

Vargan
  • 1,277
  • 1
  • 11
  • 35
1

If you don't want to sort you can check lower number and it's position and replace. 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;
}

OUTPUT:

[43, 55, 56, 46, 87]
Jordi Castilla
  • 26,609
  • 8
  • 70
  • 109
1

Here is another approach:

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;
}
SomeJavaGuy
  • 7,307
  • 2
  • 21
  • 33
1

You could do this properly in an OOp way. This maintains a list of the n largest values of a list of offered values.

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

For larger numbers you can improve the algorithm using binarySearch to find the best place to put the new item instead of blindly walking the whole list. This has the added benefit of returning a sorted list.

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;
    }
}
OldCurmudgeon
  • 64,482
  • 16
  • 119
  • 213
1

try :

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

output:

Largest 5 is: [87, 56, 55, 46, 43]
Rustam
  • 6,485
  • 1
  • 25
  • 25
0

Simple working solution for this for all condition is as given below. Please refer code below and let me know in case of any issue in comments.

public static void main(String[] args) {
    int arr[] = {75, 4, 2, 43, 56, 1,66};
    int k = 5;
    int result = find5thMaxValueApproach3(arr, k);
    System.out.println("\n 5th largest element is : " + result);
}

static int find5thMaxValueApproach3(int arr[], int k){
    int newMax = 0;
    int len = arr.length;
    int lastMax = Integer.MAX_VALUE;

    for(int j = 0; j < k; j++){

        int i = 0;
        while(arr[i] >= lastMax )
            i++;
        if(i >= len)
            break;
        
        newMax = arr[i];
        for( ; i < len; i++){
            if( arr[i] < lastMax &&  arr[i] > newMax){
                newMax = arr[i];
            }
        }
        System.out.println("newMax =" + newMax+ " lastMax="+ lastMax);
        lastMax = newMax;
    }
    return lastMax;
}
yuvraj
  • 181
  • 1
  • 12