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
、この場合、その自然な順序に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());
ラムダ関数は2つの整数を入力パラメーターとして受け取り、それらを互いに減算して、算術結果を返します。ラムダ関数は、機能インターフェイスを実装しComparator<T>
ます。(これは、匿名クラスや個別の実装とは対照的に、適切に使用されます。)
(x, y) -> y - x
オーバーフローが原因で、long整数にはlikeのようなコンパレーターが適切でない場合があります。たとえば、数値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);
追加されたbaを置き換える必要がありますJava 8
優先度キューの要素は、それらの自然な順序に従って、またはキューの構築時に提供されるコンパレーターによって順序付けられます。
コンパレータは、compareメソッドをオーバーライドする必要があります。
int compare(T o1, T o2)
デフォルトの比較メソッドは、最初の引数が2番目の引数より小さい、等しい、または大きいため、負の整数、ゼロ、または正の整数を返します。
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になります
これは、コンパレーターのみを使用するコンストラクターを導入したJava 8の以下のコードによって実現できます。
PriorityQueue<Integer> maxPriorityQ = new PriorityQueue<Integer>(Collections.reverseOrder());
使用できますMinMaxPriorityQueue
(これはGuavaライブラリーの一部です):
ここにドキュメントがあります。の代わりにpoll()
、pollLast()
メソッドを呼び出す必要があります。
PriorityQueueをMAX PriorityQueueに変更するメソッド1:Queue pq = new PriorityQueue <>(Collections.reverseOrder()); 方法2:Queue 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
*/
}
}
ご覧のとおり、どちらも同じ結果を出しています。
ダブルヒープソート最小値と最大値の両方のコンパレータでモンテカルロシミュレーションを実行したところ、どちらも同じ結果が得られました。
これらは私が使用した最大のコンパレータです:
(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;
場合は、(rhs> lhs)が-1を返す場合にそうする必要があります。
PriorityQueue<Integer> lowers = new PriorityQueue<>((o1, o2) -> -1 * o1.compareTo(o2));
これを行うには、Comparatorインターフェースを実装するCustomComparatorクラスを作成し、そのcompareメソッドをオーバーライドします。以下は同じコードです:
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;
}
}