简体   繁体   English

为我的 PriorityQueue 实现自定义比较器

[英]Implement a custom comparator for my PriorityQueue

I'm trying to solve the following leetcode problem:我正在尝试解决以下 leetcode 问题:

Given a sorted array, two integers k and x, find the k closest elements to x in the array.给定一个已排序的数组,两个整数 k 和 x,找到数组中与 x 最接近的 k 个元素。 The result should also be sorted in ascending order.结果也应按升序排序。 If there is a tie, the smaller elements are always preferred.如果有平局,则总是首选较小的元素。

Example 1: Input: [1,2,3,4,5], k=4, x=3示例 1:输入:[1,2,3,4,5], k=4, x=3

Output: [1,2,3,4]输出:[1,2,3,4]

Example 2: Input: [1,2,3,4,5], k=4, x=-1示例 2:输入:[1,2,3,4,5], k=4, x=-1

Output: [1,2,3,4]输出:[1,2,3,4]

My incorrect solution for now is the following:我现在不正确的解决方案如下:

class Solution {
    public List<Integer> findClosestElements(int[] arr, int k, int x) {
        PriorityQueue<Integer> pq = new PriorityQueue<>(arr.length, (a,b) -> a == b ? a - b : Math.abs(a-x) - Math.abs(b-x));

       for(int i=0; i<arr.length; i++) {
           pq.add(arr[i]);

       }



        ArrayList ints = new ArrayList<>();

        for(int i=0;i<k;i++) {
            ints.add(pq.poll());


        }
        return ints;
    }
}

The problem is with the comparator I'm passing to the constructor.问题在于我传递给构造函数的比较器。 The idea is that I want my comparator to sort the integers with respect to the minimum distance between any integer i and the input x and then poll k elements from the queue.这个想法是我希望我的比较器根据任何整数 i 和输入x之间的最小距离对整数进行排序,然后从队列中轮询k元素。 How can I impelement a comparator function that sorts the elements that way?如何实现以这种方式对元素进行排序的比较器函数?

I would take advantage of the default Integer.compare method.我会利用默认的Integer.compare方法。 Basically what you want is to first check the compare of the absolute difference, and if its a tie do a normal compare.基本上你想要的是首先检查绝对差异的比较,如果是平局,则进行正常比较。

static int compare(int x, int a, int b) {
    int comp = Integer.compare(Math.abs(a - x), Math.abs(b - x));
    if (comp == 0) {
        return Integer.compare(a, b);
    }
    return comp;
}

This makes it pretty clean to write the actual priority queue implementation这使得编写实际的优先级队列实现变得非常干净

static List<Integer> findClosestElements(int[] arr, int k, int x) {
    PriorityQueue<Integer> queue = new PriorityQueue<>(
        arr.length, (a,b) -> compare(x, a, b));
    Arrays.stream(arr).forEach(queue::add);
    return queue.stream().limit(k).sorted().collect(Collectors.toList());
}

In your implementation, you are not checking for the scenario where the distance of two integers is same from X.在您的实现中,您没有检查两个整数与 X 的距离相同的情况。
Following Comparator implementation would give correct result:以下比较器实现将给出正确的结果:

PriorityQueue<Integer> pq = new PriorityQueue<>(arr.length, 
                (a,b) -> {
                    int comp = Integer.compare(Math.abs(a - x), Math.abs(b - x));
                    if(comp==0) {return Integer.compare(a, b);}
                    return comp;
                });

Here, the problem is not with your priority queue but we need two results with different ordering formats.在这里,问题不在于您的优先级队列,而是我们需要两个具有不同排序格式的结果。 Your queue will give top K elements but that will never be in ascending order as it orders element with respect to distance from "X", So for given X=4, elements 3 and 5 both are at the same level so your result will have data like [4,3,5].您的队列将提供前 K 个元素,但它永远不会按升序排列,因为它根据与“X”的距离对元素进行排序,因此对于给定的 X=4,元素 3 和 5 都处于同一级别,因此您的结果将具有数据如 [4,3,5]。

Better to have separate sort for result list.最好对结果列表进行单独排序。

do Collections.sort(ints);Collections.sort(ints); and return the result.并返回结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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