Java 为my PriorityQueue实现自定义比较器
我试图解决以下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] 目前我的错误解决方案如下: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
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
)我总是选择只调用一个内置的。以牺牲额外的方法调用为代价,从大量的错误中保存代码。只有当它是一个超级紧密的循环时,才会手动滚动。