This is a difficult question to answer for two reasons:
- Firstly, method #1 and method #2 do not do the same thing, so comparing their efficiency doesn't really make sense.
- Secondly, what method #1 actually does is a bit difficult to pin down exactly, and it's not clear that what it actually does is the same as what it should do. That is, method #1 is not just a solution to a different problem; I suspect it is an incorrect solution to a different problem.
Let me explain. Method #2 is quite straightforward: it finds the maximum element from the subarray array[0..k]. Method #1 clearly does not do this: it only reads data from the subarray array[k..n].
It also clearly isn't finding the maximum from that subarray, because it puts data into smallArray, sorts it, and returns the value from index 0; the maximum would be at index k - 1. But the value at index 0 is also not the minimum, since data only gets put into smallArray if it's bigger than what's already there.
The actual behaviour of method #1 can be investigated using examples. For convenience, I've changed the signature to take array and k as parameters:
findLarger(new int[] { 1, 2, 3, 4, 5, 6, 7 }, 3) is 5: the third-largest of 4, 5, 6, 7.
findLarger(new int[] { 1, 2, 3, 7, 6, 5, 4 }, 3) is also 5: the third-largest of 7, 6, 5, 4.
findLarger(new int[] { 7, 6, 5, 4, 3, 2, 1 }, 3) is 2: the third-largest of 4, 3, 2, 1.
findLarger(new int[] { 1, 2, 3, 7, 6, 5, 4 }, 1) is 7: the first-largest of
2, 3, 7, 6, 5, 4.
For these examples, it consistently returns the kth largest element in the subarray array[k..n]. However, in other cases, it doesn't:
findLarger(new int[] { -1, -2, -3, -4, -5, -6 }, 2) is 0, not one of -3, -4, -5, -6.
findLarger(new int[] { 1, 2, 3, 4, 5, 6, 7 }, 5) is 0, not one of 6, 7.
So the full statement of what method #1 does is: it returns the kth largest positive element from the subarray array[k..n], or 0 if this sub-array contains fewer than k positive numbers. The special case of returning 0, and the use of k for two unrelated purposes, suggests that this method was supposed to solve the more straightforward problem of returning the kth largest element, but that it was written incorrectly.
Further evidence for this is that a very simple change to the algorithm makes it unconditionally return the kth largest element: instead of initialising smallArray with zeroes, copy the first k elements from array and sort them.
// changed: copy first k elements from array, and sort
int[] smallArray = Arrays.copyOfRange(array, 0, k);
Arrays.sort(smallArray);
for (int index = k; index < array.length; index++){
if (array[index] > smallArray[0]){
smallArray[0] = array[index];
Arrays.sort(smallArray);
}
}
return smallArray[0];
Even more evidence is the similarity with the code in this other Stack Overflow question, which is meant to find the kth largest element, and which does the copyOfRange and sort instead of just new int[k].
So now we can talk about the efficiency of alternatives to the fixed version of method #1.
The time complexity of method #1 is O(nk log k).
Method #1 can be improved to O(nk) by changing Arrays.sort in the inner loop to shift the first element to its correct position in O(k) time; this works because only the first element will be out of order, so a full sort is unnecessary.
The obvious way to find the kth largest element is to sort the array and return the value at index n - k. This takes O(n log n) time; method #1 is only better when k log k < log n, i.e. when k is small compared to n.
You can do better - the quickselect algorithm takes just O(n) time on average, which is clearly optimal for this problem. However, it has a rare worst-case complexity of O(n²).
getArray()andgetIndex()?