I am trying to solve a task that asks me to find the largest kth element in an unsorted array of length n (n might be as large as 5,000,000; elements in the array are distinct). Due to the task limits, I cannot use any sorting method, PriorityQueue, etc. Also, I used the user-defined FastReader class instead of the Scanner class to make it faster.
I have implemented the following code, which uses a temporary array of length k to store the first k elements and renew the smallest element through the process of reading.
import java.io.*;
import java.util.StringTokenizer;
public class lazyArray
{
public static void main(String[] args)
{
FastReader in = new FastReader();
int n = in.nextInt(), k = in.nextInt();
int[] arr = new int[k];
for (int i = 0; i < k; i++) arr[i] = in.nextInt();
int min_index = getMinIndex(arr);
int next_num;
for (int i = k; i < n; i++)
{
next_num = in.nextInt();
if (arr[min_index] < next_num)
{
arr[min_index] = next_num;
min_index = getMinIndex(arr);
}
}
System.out.println(arr[min_index]);
}
static int getMinIndex(int[] arr)
{
int minValue = arr[0];
int index = 0;
for(int i = 1; i < arr.length; i++)
{
if(arr[i] < minValue) {
minValue = arr[i];
index = i;
}
}
return index;
}
static class FastReader
{
BufferedReader br;
StringTokenizer st;
public FastReader()
{
br = new BufferedReader(new InputStreamReader(System.in));
}
String next()
{
while (st == null || !st.hasMoreElements()) {
try {
st = new StringTokenizer(br.readLine());
}
catch (IOException e) {
e.printStackTrace();
}
}
return st.nextToken();
}
int nextInt() { return Integer.parseInt(next()); }
}
}
However, the online judge platform returns an OutOfMemoryError.
I guess the error happens when n is near 5,000,000. I have tried to avoid initializing an array with length n which probably causes memory error. But I cannot find any other possible causes for the error.
Please help me. Thanks in advance.
I just tested it locally and the problem with your memory is: the BufferedReader. When the input is a single line, you try to read it into memory all at once - and this takes quite some heap. With just 137MB of heap, your code runs smoothly.
Also your
FastReaderhas a quite high initialization time, but at 5 million input numbers this is not so much important anylonger.Anyways I developed a
FasterReaderthat is a bit faster (at least when it comes to read in 5 million values from a single line) and uses much less RAM:Its very very basic, doesn't really care about number formats. I would nearly never use it in production code!
-sign--sign can appear anywhere: before, inside or after the number, just not separated from it-signs will "flip" the sign of the number multiple timesI tried to tweak the performance of my
FasterReaderby wrapping theInputStreamwith aBufferedInputStreambut that didn't work well. Maybe it would help for reading a file, but for STDIN it made things worse.You can test the memory limitation on your local machine with the commandline parameter
-Xmx128M, to measure the time you could insert the following:It prints the number of milliseconds that your code took to run.
Btw: the highest runtime will occur when
k = n/2as then the count of numbers in the array and the count of numbers that are compared with them are both maximized. With this k you probably will not reach the limit of 2000ms forn=5_000_000, no matter how fast your reader is! But of course this absolute timelimit depends on the actual machine the code is running on.