Java of Integers에 우선 순위 대기열이 있습니다.
PriorityQueue<Integer> pq= new PriorityQueue<Integer>();
전화 pq.poll()
하면 최소 요소를 얻습니다.
질문 : 최대 요소를 얻기 위해 코드를 변경하는 방법은 무엇입니까?
Java of Integers에 우선 순위 대기열이 있습니다.
PriorityQueue<Integer> pq= new PriorityQueue<Integer>();
전화 pq.poll()
하면 최소 요소를 얻습니다.
질문 : 최대 요소를 얻기 위해 코드를 변경하는 방법은 무엇입니까?
답변:
다음과 같이 어떻습니까?
PriorityQueue<Integer> queue = new PriorityQueue<>(10, Collections.reverseOrder());
queue.offer(1);
queue.offer(2);
queue.offer(3);
//...
Integer val = null;
while( (val = queue.poll()) != null) {
System.out.println(val);
}
는 Collections.reverseOrder()
제공 Comparator
의 요소 정렬 할 것이라고 PriorityQueue
이 경우 자연 순서 a를 oposite 순서를.
Collections.reverseOrder()
비교기를 가져 오기 위해 오버로드되기 때문에 사용자 지정 개체를 비교하는 경우에도 작동합니다.
PriorityQueue(Comparator<? super E> comparator)
있습니다.
Java 8부터 람다 식을 사용할 수 있습니다.
다음 코드는 더 큰 10을 인쇄합니다.
// There is overflow problem when using simple lambda as comparator, as pointed out by Фима Гирин.
// PriorityQueue<Integer> pq = new PriorityQueue<>((x, y) -> y - x);
PriorityQueue<Integer> pq =new PriorityQueue<>((x, y) -> Integer.compare(y, x));
pq.add(10);
pq.add(5);
System.out.println(pq.peek());
람다 함수는 두 개의 정수를 입력 매개 변수로 취하고 서로 빼고 산술 결과를 반환합니다. 람다 함수는 기능 인터페이스 인 Comparator<T>
. (이는 익명 클래스 또는 개별 구현과는 반대로 제자리에 사용됩니다.)
(x, y) -> y - x
는 오버플로로 인해 긴 정수에 적합하지 않을 수 있습니다. 예를 들어, 숫자 y = Integer.MIN_VALUE 및 x = 5는 양수입니다. 사용하는 것이 좋습니다 new PriorityQueue<>((x, y) -> Integer.compare(y, x))
. 하지만 더 나은 솔루션은 @Edwin Dalorzo가 Collections.reverseOrder()
.
Comparator
요소의 순위를 역순 으로 지정하는 사용자 지정 개체를 제공 할 수 있습니다 .
PriorityQueue<Integer> pq = new PriorityQueue<Integer>(defaultSize, new Comparator<Integer>() {
public int compare(Integer lhs, Integer rhs) {
if (lhs < rhs) return +1;
if (lhs.equals(rhs)) return 0;
return -1;
}
});
이제 우선 순위 큐는 모든 비교를 역순으로 수행하므로 최소 요소가 아닌 최대 요소를 얻을 수 있습니다.
도움이 되었기를 바랍니다!
if (rhs < lhs) return +1;
if (rhs > lhs) return -1;
if (lhs < rhs) return +1; if (lhs > rhs) return -1;
PriorityQueue<Integer> pq = new PriorityQueue<Integer> (
new Comparator<Integer> () {
public int compare(Integer a, Integer b) {
return b - a;
}
}
);
b-a
발생할 수 overflow
있으므로 것은 그것을 사용하지 않아야하고 사용한다 Collections.reverseOrder();
비교기 나와 바 교체 Integer.compare(a,b);
에 추가되었습니다Java 8
Java 8 이상에서는 다음 방법 중 하나를 통해 최대 우선 순위 대기열을 만들 수 있습니다.
방법 1 :
PriorityQueue<Integer> maxPQ = new PriorityQueue<>(Collections.reverseOrder());
방법 2 :
PriorityQueue<Integer> maxPQ = new PriorityQueue<>((a,b) -> b - a);
방법 3 :
PriorityQueue<Integer> maxPQ = new PriorityQueue<>((a,b) -> b.compareTo(a));
우선 순위 큐의 요소는 자연스러운 순서에 따라 또는 큐 생성시 제공되는 비교기에 의해 정렬됩니다.
비교기는 비교 방법을 재정의해야합니다.
int compare(T o1, T o2)
기본 비교 메서드는 첫 번째 인수가 두 번째 인수보다 작거나 같거나 크므로 음의 정수, 0 또는 양의 정수를 반환합니다.
Java에서 제공하는 기본 PriorityQueue는 Min-Heap입니다. 최대 힙을 원하는 경우 다음 코드가 있습니다.
public class Sample {
public static void main(String[] args) {
PriorityQueue<Integer> q = new PriorityQueue<Integer>(new Comparator<Integer>() {
public int compare(Integer lhs, Integer rhs) {
if(lhs<rhs) return +1;
if(lhs>rhs) return -1;
return 0;
}
});
q.add(13);
q.add(4);q.add(14);q.add(-4);q.add(1);
while (!q.isEmpty()) {
System.out.println(q.poll());
}
}
}
참조 : https://docs.oracle.com/javase/7/docs/api/java/util/PriorityQueue.html#comparator ()
다음은 Java의 샘플 Max-Heap입니다.
PriorityQueue<Integer> pq1= new PriorityQueue<Integer>(10, new Comparator<Integer>() {
public int compare(Integer x, Integer y) {
if (x < y) return 1;
if (x > y) return -1;
return 0;
}
});
pq1.add(5);
pq1.add(10);
pq1.add(-1);
System.out.println("Peek: "+pq1.peek());
출력은 10입니다.
사용할 수 있습니다 MinMaxPriorityQueue
(Guava 라이브러리의 일부) :
여기에 문서가 있습니다. 대신 메서드 poll()
를 호출해야합니다 pollLast()
.
PriorityQueue를 MAX PriorityQueue로 변경 방법 1 : 대기열 pq = new PriorityQueue <> (Collections.reverseOrder ()); 방법 2 : 대기열 pq1 = new PriorityQueue <> ((a, b)-> b-a); 몇 가지 예를 살펴 보겠습니다.
public class Example1 {
public static void main(String[] args) {
List<Integer> ints = Arrays.asList(222, 555, 666, 333, 111, 888, 777, 444);
Queue<Integer> pq = new PriorityQueue<>(Collections.reverseOrder());
pq.addAll(ints);
System.out.println("Priority Queue => " + pq);
System.out.println("Max element in the list => " + pq.peek());
System.out.println("......................");
// another way
Queue<Integer> pq1 = new PriorityQueue<>((a, b) -> b - a);
pq1.addAll(ints);
System.out.println("Priority Queue => " + pq1);
System.out.println("Max element in the list => " + pq1.peek());
/* OUTPUT
Priority Queue => [888, 444, 777, 333, 111, 555, 666, 222]
Max element in the list => 888
......................
Priority Queue => [888, 444, 777, 333, 111, 555, 666, 222]
Max element in the list => 888
*/
}
}
유명한 인터뷰 문제 : PriorityQueue를 사용하는 어레이에서 K 번째로 큰 요소
public class KthLargestElement_1{
public static void main(String[] args) {
List<Integer> ints = Arrays.asList(222, 555, 666, 333, 111, 888, 777, 444);
int k = 3;
Queue<Integer> pq = new PriorityQueue<>(Collections.reverseOrder());
pq.addAll(ints);
System.out.println("Priority Queue => " + pq);
System.out.println("Max element in the list => " + pq.peek());
while (--k > 0) {
pq.poll();
} // while
System.out.println("Third largest => " + pq.peek());
/*
Priority Queue => [888, 444, 777, 333, 111, 555, 666, 222]
Max element in the list => 888
Third largest => 666
*/
}
}
또 다른 방법 :
public class KthLargestElement_2 {
public static void main(String[] args) {
List<Integer> ints = Arrays.asList(222, 555, 666, 333, 111, 888, 777, 444);
int k = 3;
Queue<Integer> pq1 = new PriorityQueue<>((a, b) -> b - a);
pq1.addAll(ints);
System.out.println("Priority Queue => " + pq1);
System.out.println("Max element in the list => " + pq1.peek());
while (--k > 0) {
pq1.poll();
} // while
System.out.println("Third largest => " + pq1.peek());
/*
Priority Queue => [888, 444, 777, 333, 111, 555, 666, 222]
Max element in the list => 888
Third largest => 666
*/
}
}
보시다시피, 둘 다 동일한 결과를 제공합니다.
방금 double heap sort min max의 두 비교기에서 Monte-Carlo 시뮬레이션을 실행했는데 둘 다 동일한 결과를 얻었습니다.
다음은 내가 사용한 최대 비교기입니다.
(A) 컬렉션 내장 비교기
PriorityQueue<Integer> heapLow = new PriorityQueue<Integer>(Collections.reverseOrder());
(B) 맞춤형 비교기
PriorityQueue<Integer> heapLow = new PriorityQueue<Integer>(new Comparator<Integer>() {
int compare(Integer lhs, Integer rhs) {
if (rhs > lhs) return +1;
if (rhs < lhs) return -1;
return 0;
}
});
if (rhs < lhs) return +1;
경우 if (rhs> lhs) return -1;
Comparator 인터페이스를 구현하는 CustomComparator 클래스를 만들고 비교 메서드를 재정 의하여이를 수행 할 수 있습니다 . 다음은 동일한 코드입니다.
import java.util.PriorityQueue;
import java.util.Comparator;
public class Main
{
public static void main(String[] args) {
PriorityQueue<Integer> nums = new PriorityQueue<>(new CustomComparator());
nums.offer(21);
nums.offer(1);
nums.offer(8);
nums.offer(2);
nums.offer(-4);
System.out.println(nums.peek());
}
}
class CustomComparator implements Comparator<Integer>{
@Override
public int compare(Integer n1, Integer n2){
int val = n1.compareTo(n2);
if(val > 0)
return -1;
else if(val < 0)
return 1;
else
return 0;
}
}