En el primer día de 2022, tigre ah tigre ah, ¡les deseo a todos un próspero año del tigre! ! ! Ya está aquí el primer blog del año.
contenido
3.1 Anulando el igual de la clase base
3.2 Comparación basada en la clase de interfaz Comparble
3.3 Comparación basada en comparador
3.4 Comparación de tres métodos
6. El problema del montón que sobró de la última lección
6.2 Preguntas de la entrevista
1. Hacer preguntas
En el blog anterior, premiamos la cola de prioridad. La cola de prioridad tiene un requisito al insertar elementos: el elemento insertado no puede ser nulo o los elementos deben compararse . Para simplificar, solo insertamos el tipo Entero , la prioridad Puede ¿Insertas objetos de tipo personalizado en la cola?Vamos a ver①Cuando el elemento insertado es nulo: (No importa cuándo inserte nulo, se informará una excepción de puntero nulo)
2. Comparación de elementos
2.1 Comparación de tipos básicos
En Java , los objetos de tipos primitivos se pueden comparar directamente en tamaño.
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 Comparación de objetos
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. Comparación de objetos
En algunos casos, es necesario comparar el contenido del objeto. Por ejemplo, cuando se inserta un objeto en la cola de prioridad, el almacenamiento dinámico debe ajustarse de acuerdo con el contenido del objeto. ¿Cómo solucionarlo?
3.1 Anulando el igual de la clase base
Nota: cuando un tipo personalizado quiera comparar si los dos son iguales y tienen el mismo contenido, asegúrese de anular su método de igualdad.
Modificar el código a:
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)); }
Nota: La rutina general para anular los iguales es como se muestra arriba1. Si apunta al mismo objeto, devuelve verdadero2. Si la entrada es nula , devuelve falso3. Si el tipo de objeto entrante no es Tarjeta , devuelve falso4. Complete la comparación de acuerdo con el objetivo de realización de la clase, por ejemplo, siempre que el palo y el valor sean iguales, se considera que es la misma carta5. Tenga en cuenta que la comparación de otros tipos de referencia también requiere iguales , como la comparación de traje aquíAunque se puede comparar el método de anular la clase base equal , el defecto es: equal solo se puede comparar de acuerdo con la igualdad, y no se puede comparar de acuerdo con mayor que o menor que . v
3.2 Comparación basada en la clase de interfaz Comparble
Para tener la capacidad de comparar, implemente la interfaz Comparable aquí y compare las partes específicas que necesita (el valor predeterminado aquí es la comparación de montones pequeños)
el código se muestra a continuación:
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 Comparación basada en comparador
el código se muestra a continuación:
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); }
También puede utilizar los siguientes dos métodos:
Método 1: clase interna anónima
PriorityQueue<Card> priorityQueue = new PriorityQueue<>(new Comparator<Card>() { @Override public int compare(Card o1, Card o2) { return o1.rank-o2.rank; } });
Método ②: expresión lambda
PriorityQueue<Card> priorityQueue = new PriorityQueue<>((x,y)->{return y.rank-x.rank;});
3.4 Comparación de tres métodos
compareTo está más inclinado a las clases
6. El problema del montón que sobró de la última lección
6.1 Problema TopK
Idea ①: Ordene el conjunto y genere los 10 elementos más grandes. (manera habitual de pensar)
Idea 2: use el montón que acaba de aprender antes
Idea ③: a. Primero cree los primeros 3 elementos como un montón raíz pequeño
b. Debido a que el montón actual es un montón raíz pequeño, entonces el elemento superior del montón debe ser el más pequeño de los primeros k elementos. Si hay un elemento más grande que el elemento superior del montón, reemplaza el elemento superior del montón y este elemento puede ser uno de los superiores. Por el contrario, si se trata de un montón raíz grande, no es necesariamente
c. Después de sacar el elemento superior del montón, se ajustará de nuevo a un montón raíz pequeño.
el código se muestra a continuación: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)); } }
Problema de clasificación de montón:
Ideas para resolver problemas: (la condición final es que el final sea 0)
① Ajuste el montón a un gran montón raíz
②El subíndice 0 se puede intercambiar con el último elemento sin clasificar
③fin--
④ Ajuste el montón hacia abajo de nuevo al montón de raíz grande
el código se muestra a continuación:
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 Preguntas de la entrevista
tema:
Dadas dos matrices de enteros nums1 y nums2 en orden ascendente, y un entero k.
Defina un par de valores (u,v) donde el primer elemento proviene de nums1 y el segundo elemento proviene de nums2.
Encuentra los k pares con la suma más pequeña (u1,v1), (u2,v2) ... (uk,vk) .
Idea para resolver problemas: (en realidad también es un problema topK, la diferencia es que se cambia a la suma más pequeña de los primeros k)
? ? ? la pregunta es esa? ? ? Cómo poner un conjunto de pares
PriorityQueue<Lista<Entero>>
el código se muestra a continuación:
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); }
Gracias por leer~~~