Le premier jour de 2022, tigre ah tigre ah, je souhaite à tous une année prospère du tigre ! ! ! Le premier blog de l'année est ici
teneur
3.1 Remplacer l'égal de la classe de base
3.2 Comparaison basée sur la classe d'interface Comparble
3.3 Comparaison basée sur un comparateur
3.4 Comparaison de trois méthodes
6. Le problème du tas restant de la dernière leçon
1. Poser des questions
Dans le blog précédent, nous avons récompensé la file d'attente prioritaire. La file d'attente prioritaire a une exigence lors de l'insertion d'éléments : l'élément inséré ne peut pas être nul ou les éléments doivent pouvoir être comparés . Pour simplifier, nous insérons simplement le type Integer , la priorité Peut vous insérez des objets de type personnalisé dans la file d'attente ?Nous allons jeter un coup d'oeil①Lorsque l'élément inséré est nul : (Peu importe quand vous insérez null, une exception de pointeur nul sera signalée)
2. Comparaison des éléments
2.1 Comparaison des types de base
En Java , les objets de types primitifs peuvent être directement comparés en taille.
public class TestCompare {
public static void main(String[] args) {
//①整型数据的比较
int a = 10; int b = 20;
System.out.println(a > b);
System.out.println(a < b);
System.out.println(a == b);
//②字符型数据的比较
char c1 = 'A';
char c2 = 'B';
System.out.println(c1 > c2);
System.out.println(c1 < c2);
System.out.println(c1 == c2);
//布尔类型数据的比较
boolean b1 = true;
boolean b2 = false;
System.out.println(b1 == b2);
System.out.println(b1 != b2); } }
2.2 Comparaison des objets
class Card { public int rank; // 数值 public String suit; // 花色 public Card(int rank, String suit) { this.rank = rank; this.suit = suit; } } public class TestPriorityQueue { public static void main(String[] args) { Card c1 = new Card(1, "♠"); Card c2 = new Card(2, "♠"); Card c3 = c1; System.out.println(c1 > c2); // 编译报错 System.out.println(c1 == c2); // 编译成功 ----> 打印false,因为c1和c2指向的是不同对象 System.out.println(c1 < c2); // 编译报错 System.out.println(c1 == c3); // 编译成功 ----> 打印true,因为c1和c3指向的是同一个对象 } }
3. Comparaison d'objets
Dans certains cas, le contenu de l'objet doit être comparé. Par exemple, lorsqu'un objet est inséré dans la file d'attente prioritaire, le tas doit être ajusté en fonction du contenu de l'objet. Comment gérer cela ?
3.1 Remplacer l'égal de la classe de base
Remarque : lorsqu'un type personnalisé veut comparer si les deux sont identiques et ont le même contenu, assurez-vous de remplacer sa méthode equals
Modifiez le code pour :
class Card{ public int rank; public String suit; public Card(int rank, String suit) { this.rank = rank; this.suit = suit; } @Override public String toString() { return "Card{" + "rank=" + rank + ", suit='" + suit + '\'' + '}'; } @Override public boolean equals(Object o) { //如果this引用和o引用 引用的是同一个对象 if (this == o) return true; //getClass()这里比较的是是不是同一个类型,不是的话返回false;当然此处可以用instanceof来判断 //if (o == null || !(o instanceof Card))可以用此语句来代替 if (o == null || getClass() != o.getClass()) return false; Card card = (Card) o; //数字一样并且花色一样,那么逻辑上就是一样的 return rank == card.rank && Objects.equals(suit, card.suit); } @Override public int hashCode() { return Objects.hash(rank, suit); } } public class TestDemo { public static void main(String[] args) { Card card1 = new Card(1, "♥"); Card card2 = new Card(1, "♥"); System.out.println(card1.equals(card2)); }
Remarque : La routine générale pour remplacer les égaux est comme démontré ci-dessus1. S'il pointe vers le même objet, retourne true2. Si l'entrée est null , retourne false3. Si le type d'objet entrant n'est pas Card , renvoyez false4. Complétez la comparaison en fonction de l'objectif de réalisation de la classe Par exemple, tant que la couleur et la valeur sont identiques, on considère qu'il s'agit de la même carte5. Notez que la comparaison d'autres types de référence nécessite également des égaux , comme la comparaison de costume iciBien que la méthode de remplacement de la classe de base equal puisse être comparée, le défaut est le suivant : equal ne peut être comparé qu'en fonction de l'égalité, et ne peut pas être comparé en fonction de supérieur ou inférieur à . v
3.2 Comparaison basée sur la classe d'interface Comparble
Afin d'avoir la possibilité de comparer, implémentez l'interface Comparable ici et comparez les pièces spécifiées dont vous avez besoin (la valeur par défaut ici est la comparaison de petits tas)
code afficher comme ci-dessous:
import java.util.PriorityQueue; //要具备比较的能力 class Card implements Comparable<Card>{ public int rank; public String suit; public Card(int rank, String suit) { this.rank = rank; this.suit = suit; } @Override public String toString() { return "Card{" + "rank=" + rank + ", suit='" + suit + '\'' + '}'; } @Override public int compareTo(Card o) { //自己定义比较的内容 return o.rank-this.rank; } } public class TestDemo { public static void main(String[] args) { //默认底层为小根堆,每存入一个元素均会进行比较 PriorityQueue<Card>priorityQueue=new PriorityQueue<>(); priorityQueue.offer(new Card(2,"♥"));//存取第一个元素时实际上是直接放到底层的queue数组的0下标 priorityQueue.offer(new Card(1,"♥")); System.out.println(priorityQueue); }
3.3 Comparaison basée sur un comparateur
code afficher comme ci-dessous:
import java.util.Comparator; import java.util.PriorityQueue; //要具备比较的能力 class Card{ public int rank; public String suit; public Card(int rank, String suit) { this.rank = rank; this.suit = suit; } @Override public String toString() { return "Card{" + "rank=" + rank + ", suit='" + suit + '\'' + '}'; } } class RankCompartor implements Comparator<Card>{ @Override public int compare(Card o1, Card o2) { return o1.rank-o2.rank; } } public class TestDemo { public static void main(String[] args) { //默认底层为小根堆,每存入一个元素均会进行比较 Card card1=new Card(1,"♥"); Card card2=new Card(2,"♥"); RankCompartor rankCompartor=new RankCompartor(); int ret=rankCompartor.compare(card1,card2); System.out.println(ret); }
Vous pouvez également utiliser les deux méthodes suivantes :
Méthode 1 : classe interne anonyme
PriorityQueue<Card> priorityQueue = new PriorityQueue<>(new Comparator<Card>() { @Override public int compare(Card o1, Card o2) { return o1.rank-o2.rank; } });
Méthode ② : expression lambda
PriorityQueue<Card> priorityQueue = new PriorityQueue<>((x,y)->{return y.rank-x.rank;});
3.4 Comparaison de trois méthodes
compareTo est plus enclin aux classes
6. Le problème du tas restant de la dernière leçon
6.1 Problème TopK
Idée ① : triez le tout et affichez les 10 éléments les plus grands. (façon habituelle de penser)
Idée 2 : Utilisez le tas que vous venez d'apprendre
Idée ③ : a. Créez d'abord les 3 premiers éléments comme un petit tas racine
b. Parce que le tas actuel est un petit tas racine, alors l'élément supérieur du tas doit être le plus petit des k premiers éléments. S'il y a un élément plus grand que l'élément supérieur du tas, il remplace l'élément supérieur du tas, et cet élément peut être l'un des topks. Au contraire, s'il s'agit d'un grand tas racine, ce n'est pas nécessairement
C. Une fois l'élément supérieur du tas retiré, il sera à nouveau ajusté en un petit tas racine.
code afficher comme ci-dessous:import java.util.Arrays; import java.util.Comparator; import java.util.PriorityQueue; //求数组中前k个最小的元素,建大堆 public class TopK { public static int[] topK(int []array,int k){ //创建一个大小为k的大根堆 PriorityQueue<Integer> maxHeap=new PriorityQueue<>(k, new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return o2-o1; } }); //遍历数组当中的元素,将前k个元素放入队列中 for (int i = 0; i < array.length ; i++) { if(maxHeap.size()<k){ maxHeap.offer(array[i]); }else{ //从k+1个元素开始,每个元素和堆顶元素进行比较 int top=maxHeap.peek(); if(top>array[i]){ //现将大的弹出 maxHeap.poll(); //再将小的存入 maxHeap.offer(array[i]); } } } int[]tmp=new int[k]; for (int i = 0; i <k ; i++) { tmp[i]=maxHeap.poll(); } return tmp; } public static void main(String[] args) { int []array={18,21,8,10,34,12}; int []tmp=topK(array,3); System.out.println(Arrays.toString(tmp)); } }
Problème de tri par tas :
Idées de résolution de problèmes : (la condition de fin est que la fin est 0)
① Ajustez le tas à un grand tas racine
②L'indice 0 peut être échangé avec le dernier élément non trié
③fin--
④ Ajustez à nouveau le tas au gros tas racine
code afficher comme ci-dessous:
public void heapSort() { int end = this.usedSize - 1; while (end > 0) { int tmp = elem[0]; elem[0] = elem[end]; elem[end] = tmp; shiftDown(0, end); end--; } }
6.2 Questions d'entrevue
sujet:
Étant donné deux tableaux d'entiers nums1 et nums2 dans l'ordre croissant, et un entier k.
Définissez une paire de valeurs (u,v) où le premier élément provient de nums1 et le deuxième élément provient de nums2 .
Trouver les k paires avec la plus petite somme (u1,v1), (u2,v2) ... (uk,vk) .
Idée de résolution de problème : (en fait, c'est aussi un problème topK, la différence est qu'il est remplacé par la plus petite somme des premiers k)
? ? ? la question c'est ça ? ? ? Comment mettre un ensemble de paires
PriorityQueue<Liste<Entier>>
code afficher comme ci-dessous:
public static List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k) { PriorityQueue<List<Integer>> maxHeap = new PriorityQueue<>(k, new Comparator<List<Integer>>() { @Override public int compare(List<Integer> o1, List<Integer> o2) { //获取List中的某个元素需要使用get()方法 return (o2.get(0)+o2.get(1))-(o1.get(0)+o1.get(1)); } }); // for (int i = 0; i < Math.min(nums1.length,k); i++) { // for (int j = 0; j < Math.min(nums2.length,k); j++) { for (int i = 0; i < nums1.length; i++) { for (int j = 0; j < nums2.length; j++) { //还没放满的情况下 if(maxHeap.size() < k) { List<Integer> tmpList = new ArrayList<>(); tmpList.add(nums1[i]); tmpList.add(nums2[j]); maxHeap.offer(tmpList); }else { //获取顶元素的值 int top = maxHeap.peek().get(0) + maxHeap.peek().get(1); if(top > nums1[i]+nums2[j]) { //记住 要弹出的 maxHeap.poll(); List<Integer> tmpList = new ArrayList<>(); tmpList.add(nums1[i]); tmpList.add(nums2[j]); maxHeap.offer(tmpList); } } } } List<List<Integer>> ret = new ArrayList<>(); for (int i = 0; i < k && !maxHeap.isEmpty(); i++) { ret.add(maxHeap.poll()); } return ret; } public static void main(String[] args) { int[] nums1 = {1,7,11}; int[] nums2 = {2,4,6}; List<List<Integer>> ret = kSmallestPairs(nums1,nums2,3); System.out.println(ret); }
Merci d'avoir lu ~~~