Java 为my PriorityQueue实现自定义比较器

Java 为my PriorityQueue实现自定义比较器,java,heap,comparator,priority-queue,Java,Heap,Comparator,Priority Queue,我试图解决以下leetcode问题: 给定一个排序数组,两个整数k和x,查找数组中与x最近的k个元素。结果也应该按升序排序。如果有一个领带,较小的元素总是首选 例1: 输入:[1,2,3,4,5],k=4,x=3 输出:[1,2,3,4] 例2: 输入:[1,2,3,4,5],k=4,x=-1 输出:[1,2,3,4] 目前我的错误解决方案如下: class Solution { public List<Integer> findClosestElements(int[] a

我试图解决以下leetcode问题:

给定一个排序数组,两个整数k和x,查找数组中与x最近的k个元素。结果也应该按升序排序。如果有一个领带,较小的元素总是首选

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

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

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

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

目前我的错误解决方案如下:

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;
    }
}
类解决方案{
公共列表查找关闭项(int[]arr,int k,int x){
PriorityQueue pq=newpriorityqueue(arr.length,(a,b)->a==b?a-b:Math.abs(a-x)-Math.abs(b-x));

对于(int i=0;i在您的实现中,您没有检查两个整数距离X相同的场景。
以下比较器实现将给出正确的结果:

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;
                });
PriorityQueue pq=新的PriorityQueue(arr.length,
(a、b)->{
int comp=Integer.compare(Math.abs(a-x),Math.abs(b-x));
如果(comp==0){返回整数。比较(a,b);}
返回补偿;
});

在您的实现中,您没有检查两个整数距离X相同的情况。
以下比较器实现将给出正确的结果:

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;
                });
PriorityQueue pq=新的PriorityQueue(arr.length,
(a、b)->{
int comp=Integer.compare(Math.abs(a-x),Math.abs(b-x));
如果(comp==0){返回整数。比较(a,b);}
返回补偿;
});

这里,问题不在于优先级队列,而是我们需要两个具有不同排序格式的结果。您的队列将给出前K个元素,但这永远不会是升序,因为它将元素按距离“X”排序,因此对于给定的X=4,元素3和5都处于同一级别,因此您的结果将包含以下数据[4,3,5]

最好对结果列表进行单独排序


执行集合。排序(ints);
并返回结果。

这里,问题不在于优先级队列,而是我们需要两个具有不同排序格式的结果。您的队列将给出前K个元素,但这永远不会是升序,因为它对元素的排序与“X”的距离有关,因此对于给定的X=4,元素3和5都处于同一级别,因此您的结果将包含类似于[4,3,5]的数据

最好对结果列表进行单独排序


执行
Collections.sort(ints);
并返回结果。

我将利用默认的
Integer.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;
}
这使得编写实际的优先级队列实现变得非常简洁

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());
}
静态列表查找关闭项(int[]arr、int k、int x){
PriorityQueue队列=新建PriorityQueue(
arr.length(a,b)->比较(x,a,b));
Arrays.stream(arr.forEach)(队列::add);
返回queue.stream().limit(k).sorted().collect(Collectors.toList());
}

我会利用默认的
整数。比较
方法。基本上,你想要的是首先检查绝对差的比较,如果是平局,则进行正常比较

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;
}
这使得编写实际的优先级队列实现变得非常简洁

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());
}
静态列表查找关闭项(int[]arr、int k、int x){
PriorityQueue队列=新建PriorityQueue(
arr.length(a,b)->比较(x,a,b));
Arrays.stream(arr.forEach)(队列::add);
返回queue.stream().limit(k).sorted().collect(Collectors.toList());
}

成功了!谢谢!您能解释一下比较器返回值是如何实际用于将元素插入堆的吗?这意味着返回值为-1 vs 1 vs 0时会发生什么情况?@saifabuhashih比较器的结果(1,-1,0)确定两个元素中哪一个大于另一个。在上面的示例中,+1表示a>b,-1表示b>a,0表示a==b。comparator的此结果有助于priorityQueue对元素进行排序。这很有效!谢谢!您是否有机会解释如何实际使用来自comparator的comparator返回值将元素插入到e heap?表示返回值为-1 vs 1 vs 0时会发生什么情况?@saifabuhashih比较器(1,-1,0)的结果确定两个元素中哪一个大于另一个。在上面的示例中,+1表示a>b,-1表示b>a,0表示a==b。comparator的这个结果有助于priorityQueue对元素进行排序。Integer.compare使它简化了很多。@Tarun绝对如此。我发现比较很容易搞乱(无论您是需要
-1
还是
1
)我总是选择只调用一个内置函数。以牺牲额外的方法调用为代价,从大量错误中保存代码。只有当它是一个超级紧密循环时,才会手动滚动。Integer.compare可以简化它很多。@Tarun绝对如此。我发现比较很容易搞砸(无论你需要
-1
还是
1
)我总是选择只调用一个内置的。以牺牲额外的方法调用为代价,从大量的错误中保存代码。只有当它是一个超级紧密的循环时,才会手动滚动。