简体   繁体   中英

How to Convert and get Negative number in to positive Numbers in an Integer Array.?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM