मैं पूर्णांक के जावा में प्राथमिकता कतार है:
PriorityQueue<Integer> pq= new PriorityQueue<Integer>();
जब मैं कॉल करता pq.poll()
हूं तो मुझे न्यूनतम तत्व मिलता है।
प्रश्न: अधिकतम तत्व प्राप्त करने के लिए कोड को कैसे बदलें?
मैं पूर्णांक के जावा में प्राथमिकता कतार है:
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
इस मामले में उनके प्राकृतिक क्रम में एक विपरीत क्रम में।
Collections.reverseOrder()
एक तुलनित्र लेने के लिए भी अतिभारित है, इसलिए यदि आप कस्टम ऑब्जेक्ट्स की तुलना करते हैं तो यह भी काम करता है।
PriorityQueue(Comparator<? super E> comparator)
।
जावा 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
जावा 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)
डिफ़ॉल्ट तुलना विधि एक नकारात्मक पूर्णांक, शून्य या एक सकारात्मक पूर्णांक लौटाती है क्योंकि पहला तर्क दूसरे के मुकाबले कम या ज्यादा होता है।
जावा द्वारा प्रदान किया गया डिफ़ॉल्ट प्राथमिकता क्यू मिन-हीप है, यदि आप चाहते हैं कि एक अधिकतम हीप निम्नलिखित कोड हो
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 ()
यहाँ जावा में एक नमूना मैक्स-हीप है:
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
(यह अमरूद पुस्तकालय का एक हिस्सा है):
यहाँ प्रलेखन है । इसके बजाय poll()
, आपको pollLast()
विधि को कॉल करने की आवश्यकता है ।
प्राथमिकता प्राथमिकता को अधिकतम प्राथमिकता में बदलें विधि 1: कतार pq = नया वरीयता क्रम <> (संग्रह .reverseOrder ()); विधि 2: कतार pq1 = नया प्राथमिकता कतार <> ((ए, बी) -> बी - ए); आइए कुछ उदाहरण देखें:
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
*/
}
}
आइए एक प्रसिद्ध साक्षात्कार समस्या लेते हैं: प्राथमिकता ऐरे का उपयोग करके ऐरे में Kth सबसे बड़ा तत्व
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
*/
}
}
जैसा कि हम देख सकते हैं, दोनों एक ही परिणाम दे रहे हैं।
मैं सिर्फ डबल हीप सॉर्ट अधिकतम पर दोनों तुलनित्र पर एक मोंटे-कार्लो सिमुलेशन चलाता था और वे दोनों एक ही परिणाम पर आए:
ये मेरे द्वारा उपयोग किए जाने वाले अधिकतम तुलनित्र हैं:
(ए) संग्रह तुलनित्र में निर्मित
PriorityQueue<Integer> heapLow = new PriorityQueue<Integer>(Collections.reverseOrder());
(बी) कस्टम तुलनित्र
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> pq = new PriorityQueue<>((x, y) -> -1 * Integer.compare(x, y));
जो आपके पास किसी अन्य आधार तुलना समारोह के लिए काम करता है।
PriorityQueue<Integer> lowers = new PriorityQueue<>((o1, o2) -> -1 * o1.compareTo(o2));
आप रिवर्स साइन के साथ पुश करने वाले तत्वों को आज़मा सकते हैं। जैसे: a = 2 और b = 5 जोड़ना और फिर b = 5 को पोल करना।
PriorityQueue<Integer> pq = new PriorityQueue<>();
pq.add(-a);
pq.add(-b);
System.out.print(-pq.poll());
एक बार जब आप कतार के प्रमुख को पोल कर लेते हैं, तो अपने उपयोग के लिए साइन को उल्टा कर दें। यह 5 (बड़ा तत्व) प्रिंट करेगा। अनुभवहीन कार्यान्वयन में इस्तेमाल किया जा सकता है। निश्चित रूप से एक विश्वसनीय तय नहीं है। मैं इसकी अनुशंसा नहीं करता।
हम अपने 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;
}
}