I had to print greatest of three numbers in an array in which negative numbers which consists of highest value need to be converted to positive.for example: input: int[] nums={3,5,8,1,2,0,-10,-20}; output: {20,10,8}.
private List<Integer> largestThreeNums(int[] nums) {
Arrays.sort(nums);
int x=nums.length;
return Arrays.asList(Math.abs(nums[x-1]),Math.abs(nums[x-2]),Math.abs(nums[x-3]));
}
If I understand the question, it is to find the three largest absolute values of the items. Here is a solution using Java streams:
Arrays.stream(nums)
.map(Math::abs).boxed()
.sorted(Comparator.reverseOrder())
.limit(3)
.toList();
This can be read as: stream the items, convert each to its absolute value, sort from largest to smallest, get the first three and covert to a list.
If you particularly need it to be efficient then you can still use streams by creating a collector:
static class TopN<T extends Comparable<T>> {
private final int limit;
private final PriorityQueue<T> largest = new PriorityQueue<>();
public TopN(int limit) {
this.limit = limit;
}
public void add(T value) {
largest.add(value);
reduce();
}
public void combine(TopN other) {
largest.addAll(other.largest);
reduce();
}
private void reduce() {
while (largest.size() > limit)
largest.poll();
}
public List<T> toList() {
return List.copyOf(largest);
}
}
Which simplifies your code to:
Arrays.stream(nums)
.map(Math::abs).boxed()
.collect(() -> new TopN<>(3), TopN::add, TopN::combine)
.toList();
This is a generic implementation which will work for any comparable class and any number of largest items you want to collect. You could even pass in a comparator and not restrict yourself to largest.
And ff you have a very large number of inputs you can even turn this into a parallel stream and it will split the work across threads.
Approach 1
You can do this using java streams with following logic.
first you use map() to get absolute values
then you sort absolute number list using sorted()
then you get first three numbers using limit()
private List<Integer> largestThreeNums(Integer[] nums) { List<Integer> numList = Arrays.asList(nums); return numList.stream().map(num -> Math.abs(num)).sorted(Comparator.reverseOrder()).limit(3).collect(Collectors.toList()); }
Approach 2
But the performance of 1st approach will be very low for larger data set because we are sorting complete array. In such scenario you can use following logic.
private List<Integer> largestThreeNumsWithoutSorting(Integer[] nums) {
List<Integer> numList = Arrays.asList(nums);
List<Integer> absNumList = numList.stream().map(num -> Math.abs(num)).collect(Collectors.toList());
int largest = absNumList.get(0);
int secondLargest = absNumList.get(0);
int thirdLargest = absNumList.get(0);
for (int num: absNumList) {
if(num >= largest) {
thirdLargest = secondLargest;
secondLargest = largest;
largest = num;
} else if (num >= secondLargest) {
thirdLargest = secondLargest;
secondLargest = num;
} else if (num >= thirdLargest) {
thirdLargest = num;
}
}
return Arrays.asList(largest, secondLargest, thirdLargest);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.