Java implementa las preguntas clásicas de la entrevista para las listas vinculadas, no diga que ha aprendido las listas vinculadas sin cepillarlas 5 veces.

          

     Las preguntas de la lista vinculada son la mejor manera de probar la profundidad de las habilidades internas del código de una persona. Después de aprender la lista vinculada al principio, escribí muchas preguntas, pero después de un período de tiempo, abrí la lista vinculada y me sentí extraño. Recordé una frase que dijo el profesor en la clase anterior: "Si no lee las preguntas de la lista enlazada 5 veces, no debe decir que ha aprendido la lista enlazada". Entonces, comencé a mirar las preguntas de la lista enlazada anterior. Las preguntas clásicas de la entrevista por encima de lettcode, los siguientes códigos están escritos de forma silenciosa.

En resumen, las preguntas clásicas de la entrevista de la lista enlazada incluyen principalmente lo siguiente:

1. Elimine todos los nodos de la lista vinculada que sean iguales al valor dado val . Enlace OJ
2. Invierta una lista enlazada individualmente. Enlace OJ
3. Dada una lista enlazada individualmente no vacía con el encabezado del nodo principal , devuelva el nodo medio de la lista enlazada. Si hay dos nodos intermedios, regrese al segundo nodo intermedio. Enlace OJ
4. Ingrese una lista vinculada y genere el k-ésimo nodo de la parte inferior de la lista vinculada . Enlace OJ
5. Combine dos listas vinculadas ordenadas en una nueva lista vinculada ordenada y regrese. La nueva lista enlazada se compone de empalmar todos los nodos de las dos listas enlazadas dadas. Enlace OJ
6. Escriba el código para dividir la lista enlazada en dos partes basándose en el valor dado x , y todos los nodos menores que x se ordenan antes que los nodos mayores o iguales ax . Enlace OJ
7. En una lista vinculada ordenada, hay nodos duplicados. Elimine los nodos duplicados en la lista vinculada. Los nodos duplicados no se conservarán y se devolverá el puntero principal de la lista vinculada. Enlace OJ
8. La estructura del palíndromo de la lista enlazada. Enlace OJ
9. Ingrese dos listas vinculadas y busque su primer nodo común. Enlace OJ
10. Dada una lista vinculada, determine si hay bucles en la lista vinculada. Enlace OJ
11. Dada una lista vinculada, devuelva el primer nodo donde la lista vinculada comienza a entrar en el anillo. Si la lista vinculada no tiene anillos, devuelva el enlace OJ  nulo 
12. Otros. Definitivamente hay otras preguntas de listas vinculadas más difíciles, puede encontrar preguntas en Niuke y Leetcode para cepillarlas.
 
 
0: lista vinculada de implementación personalizada
Algunos métodos para personalizar listas vinculadas incluyen inserción de encabezado, inserción de cola, inserción en cualquier posición, eliminación de la clave que aparece por primera vez y averiguar si la clave de palabra clave está incluida. El lugar más propenso a errores es que al insertar arbitrariamente, debe recordar atar primero la parte posterior y luego atar la parte frontal, como se muestra en la figura:
 
 
 
 
Elimine el nodo donde aparece la clave por primera vez: como se muestra en la figura siguiente, primero recorra para encontrar el nodo anterior cur para eliminar la clave, y luego ejecute la instrucción cur.next = node para completar la operación de eliminación.
 
public class Node {
    public  int data;
    public Node next;
    public Node(int data){
        this.data=data;
    }
}
public class MyLinkedList {
    private Node head;
    //头插法
    public  void addFirst(int data){
        //空表的时候
        Node node=new Node(data);
        if (this.head != null) {
            node.next = head;
        }
        head=node;

    }
    public void display(){
        Node cur=this.head;
        while(cur!=null){
            System.out.println(cur.data+"  ");
            cur=cur.next;
        }
    }
    //尾插法
    public  void addLast(int data){
        Node node=new Node(data);
        if(head==null){
            this.head=node;
        }else{
            Node cur=this.head;
            while(cur.next!=null){//cur
                cur=cur.next;
            }
            cur.next=node;
      }


    }
    //任意插
    public  void addIndex(int index,int data){
        //先要判断下标是否合法
        if(index<0||index>getLength()){
            System.out.println("下标不合法");
            return;
        }
        if(index==0){
            addFirst(data);
            return;
        }
        if(index==getLength()){
            addLast(data);
            return;
        }
        //现在在中间进行插入
        Node node=new Node(data);
        //找到要插入下标的前一个结点
        Node cur=searchPrev(index-1);
        node.next=cur.next;
        cur.next=node;

    }
    //找到要插入位置index的前一个位置index-1的位置节点
    public Node searchPrev(int index){
        Node cur=this.head;
        int count=0;
        while(count<index){
            cur=cur.next;
        }
        return cur;
    }
    public int getLength(){
        int count=0;
        Node cur=this.head;
        while(cur!=null){
            count++;
            cur=cur.next;
        }
        return count;
    }



    //删除第一次出现的key
    public  void remove(int key){
        if(this.head==null){
            return;
        }
        Node cur=searchPrevNode(key);
        //要注意cur是否没有找到。进行判断一下
        if(cur==null){
            System.out.println("没有找到你要删除的下标");
            return;
        }
        cur.next=cur.next.next;

    }
//查找要删除元素的前驱结点
    public Node searchPrevNode(int key){
        Node cur=this.head;
        while(cur!=null){

            if(cur.next.data==key){
                return cur;
            }
            cur=cur.next;
        }
        //没有找到要删的结点
        return null;
    }


    //查找关键字key是否包含在单链表中
    public boolean contains(int key){
        Node cur=this.head;
        while(cur!=null){
            if(cur.data==key){
                return true;
            }
            cur=cur.next;
        }
        return false;

    }

 

 
 
 
 
 
1. Elimine todos los nodos de la lista vinculada que sean iguales a la clave de valor dada . Por ejemplo, para eliminar el nodo con key = 33, como se muestra en la figura:  
Ideas: 1. Defina prev para que apunte a su nodo principal, y defina cur para apuntar al nodo a eliminar;
           2. Determine si el valor al que apunta cur es igual a la clave. Si son iguales: ejecute prev.next = cur.next, lo que significa que cur se elimina El nodo al que se apunta actualmente, entonces cur continúa atravesando hacia abajo;
          3. Si el valor de cur al que se refiere actualmente no es igual al valor de key, deje que prev = cur y cur continúen para recorrer hacia abajo hasta cur = nulo;
          4. Cuando cur = nulo, si todavía hay un nodo con un valor igual a clave, debe ser el nodo principal. Debido a que el nodo principal no se juzga cuando se inicia el juicio, el nodo principal El nodo debe ser juzgado a continuación. Si el valor es igual, elimínelo.
 
el código se muestra a continuación:
public void removeAllKey(int key){
        //定义一个prev指向要删除的节点的前一个
        //定义一个cur指向要删除的结点
        Node prev=this.head;
        Node cur=this.head.next;

        while(cur!=null){
            if(cur.data==key){
                prev.next=cur.next;
                cur=cur.next;
            }else{
                prev=cur;
                cur=cur.next;
            }
        }
        //现在如果有还有和key相等的值,那么一定在头节点
        if(this.head.data==key){
            this.head=this.head.next;
        }

    }
 
 
 
 
 
 
 
2. Invierta una lista enlazada individualmente. Requisito: atravesar una vez y revertir la lista vinculada.
 
Ideas: 1. Defina un nodo precursor prev y defina un cur, como se muestra en la figura;
           2. Primero cambie la relación de apuntado entre prev y cur, deje cur.next = prev, prev, luego apunte a la posición apuntada por cur, y cur continúa atravesando hasta el siguiente nodo;
           3. Si prev = null definido al principio, cuando se invierte la lista vinculada, el siguiente campo del último nodo apunta a null (el siguiente campo del nodo 123 en la figura es nulo, por lo que no es necesario intentar para encontrar el último nodo El campo siguiente se establece en nulo).
Antes de hacer las preguntas de la lista enlazada, piensa claramente en tus ideas. Debes dibujar y escribir código tú mismo. Si no sabes cómo hacerlo, haz más dibujos tú mismo. ¡Vamos, cree que definitivamente puedes hacerlo!
 
 
 
 
 
 
 
 
 
 
 
public Node reverseList(){
        Node newHead=null;
        Node prev=null;
        Node cur=this.head;
        while(cur!=null){
            Node curNext=cur.next;
            if(curNext==null){
                newHead=cur;
            }
            cur.next=prev;
            prev=cur;
            cur=curNext;
        }
        return newHead;
    }

 

3. Dada una lista enlazada individualmente no vacía con el encabezado del nodo principal , devuelva el nodo medio de la lista enlazada. Si hay dos nodos intermedios, regrese al segundo nodo intermedio. Requisitos: recorrer la lista vinculada una vez.
Idea: Defina dos referencias, una rápida y otra lenta, de modo que la rápida dé dos pasos a la vez y la lenta dé un paso a la vez. ¡La condición de bucle es rápida! = null && fast.next! = null, porque la referencia rápida va más rápido, y este orden no se puede intercambiar, porque cuando fast! = null pero fast.next = null, se producirá una excepción de puntero nulo.
 
 public Node middleNode(){
        Node fast=this.head;
        Node slow=this.head;

        while(fast!=null&&fast.next!=null){
            fast=fast.next.next;
            slow=slow.next;
        }
        return slow;
    }

 

4. Ingrese una lista vinculada y genere el k-ésimo nodo de la parte inferior de la lista vinculada .
Idea: Defina dos referencias, una rápida y otra lenta, primero deje que el paso rápido vaya k-1 y luego deje que los dos vayan sincrónicamente. En el k-ésimo nodo desde la parte inferior, cuando se le pide a Fast que realice el paso k-1 para el juicio de legitimidad, se puede realizar la optimización, es decir, cuando se le pide que realice el paso k-1, y luego juzgar si es rápido. el siguiente está vacío, si está vacío, no hay necesidad de dejar que el rápido continúe bajando, simplemente salte del bucle. (Por ejemplo: buscando el octavo nodo desde la parte inferior, pero la longitud total de la lista vinculada es solo 5, entonces no hay necesidad de dejar ir rápido k-1 = 8-1 = 7 pasos, una vez rápido. Siguiente = = nulo, devuelve directamente nulo).
 
 
 public Node findKthToTail(int k){
        if(k<0||head==null){
            return null;
        }
        //定义两个引用,fast先走k-1步,让偶让fast和slow同时开始走
        Node fast=this.head;
        Node slow=this.head;
        while(k-1>0){
            if(fast.next!=null) {
                fast = fast.next;
                k--;
            }else{
                System.out.println("k过大");
                return null;
            }
        }
        while(fast.next!=null){
            fast=fast.next;
            slow=slow.next;

        }
        return slow;

    }

 

 
 
 
 
5. Combine dos listas vinculadas ordenadas en una nueva lista vinculada ordenada y regrese. La nueva lista enlazada se compone de empalmar todos los nodos de las dos listas enlazadas dadas.
Idea: Para recorrer dos listas vinculadas, defina un nodo principal falso y conecte los nodos en las dos listas vinculadas en serie.
 
public Node mergeTwoLists(Node headA,Node headB){
        Node newHead=new Node(-1);
        Node tmp=newHead;
        
        //当前两个链表都有数据
        while(headA!=null&&headB!=null){
            if(headA.val<headB.val){
                tmp.next=headA;
                tmp=tmp.next;
                headA=headA.next;
            }else{
                tmp.next=headB;
                tmp=tmp.next;
                headB=headB.next;
            }
        }
        
        if(headA!=null){
            tmp.next=headA;
        }
        if(headB!=null){
            tmp.next=headB;
        }
        return newHead.next;
    }

 

 
 
 
 
 
 
 
6. Escriba el código para dividir la lista enlazada en dos partes basándose en el valor dado x , y todos los nodos menores que x se ordenan antes que los nodos mayores o iguales ax .
 
Idea: Como se muestra en la figura, realice una segmentación. Al insertar segmentos, es necesario juzgar si el intervalo está vacío. Finalmente, cuando los dos intervalos se fusionan, es necesario considerar si no hay elementos en los dos intervalos. ;
 
 
public Node partition(int x){
        Node bs=null;
        Node be=null;

        Node as=null;
        Node ae=null;

        Node cur=this.head;
        while(cur!=null){
            if(cur.data<x){
                //第一次插入
                if(bs==null){
                    bs=cur;
                    be=bs;
                }else{
                    be.next=cur;
                    be=cur;
                }
            }else{
                if(as==null){
                    as=cur;
                    ae=as;
                }else{
                    ae.next=cur;
                    ae=cur;
                }


            }
            cur=cur.next;
        }
        if(bs==null){
            return as;
        }
        be.next=as;
        if(as!=null){
            ae.next=null;
        }
        return as;
    }

 

 
 
 
 
7. En una lista vinculada ordenada, hay nodos duplicados. Elimine los nodos duplicados en la lista vinculada. Los nodos duplicados no se conservarán y se devolverá el puntero principal de la lista vinculada.
Idea: Para recorrer la lista vinculada, el punto clave está en una lista vinculada ordenada, así que: recorra desde el principio, busque el mismo siguiente y omítalo. Cuando encuentre múltiples valores idénticos conectados entre sí, use while () ciclo;
 
 
 
public Node deleteDuplication(){
        Node newHead=new Node(-1);
        Node tmp=newHead;
        Node cur=this.head;

        while(cur!=null){
            if(cur.next!=null&&cur.data==cur.next.data){
                //相等的时候
                while(cur.next!=null&&cur.data==cur.next.data){
                    cur=cur.next;
                }
                cur=cur.next;
            }else{
                tmp.next=cur;
                tmp=cur;
                cur=cur.next;

            }
        }
        tmp.next=null;//进行这一步的作用就是要保证不出现死循环
        return newHead.next;

    }
8. La estructura del palíndromo de la lista enlazada.
Ideas: 1. Encuentre primero el nodo intermedio;
2. Después de encontrar el nodo del medio, comience a voltear desde el medio;
3. Dos referencias van de cabeza y lentas, una empieza desde el frente y retrocede, la otra empieza desde atrás y va hacia adelante, para juzgar si los datos son los mismos, hasta que se encuentran;
 
public boolean chkPalindrome(){
        //第一步:先找到中间节点
        Node fast=this.head;
        Node slow=this.head;
        while (fast!=null&&fast.next!=null){
            fast=fast.next.next;
            slow=slow.next;
        }
        //第二步:对链表进行翻转
        Node cur=slow.next;
        while(cur!=null){
            Node curNext=cur.next;
            cur.next=slow;
            slow=cur;
            cur=curNext;
        }
//第三步:从两边开始向中间遍历,判断值是否相等
        while(this.head!=slow){//还没有相遇的时候
            if(this.head.data!=slow.data){
                return false;
            }
            //专门为偶数设计的
            if(this.head.next==slow){
                return true;
            }
            this.head=this.head.next;
            slow=slow.next;
        }
        return true;
    }
9. Ingrese dos listas vinculadas y busque su primer nodo común.
Ideas: 1. Encuentre la longitud de las dos listas enlazadas por separado;
2. Deje que la lista enlazada más larga tome el paso de la diferencia de las dos listas enlazadas;
3. Deje que dos referencias (pl, apuntando al encabezado de la lista enlazada larga y ps, apuntando al encabezado de la lista enlazada corta) vayan al mismo tiempo. Si se encuentran, entonces las dos listas enlazadas se cruzan.
 
public Node getIntersectionNode(Node headA,Node headB){
        if(headA==null||headB==null){
            return null;
        }
        int lenA=0;
        int lenB=0;
        
        Node pl=headA;
        Node ps=headB;
        
        while(ps!=null){
            lenB++;
            ps=ps.next;
        }
        while(pl!=null){
            lenA++;
            pl=pl.next;
        }
        pl=headA;
        ps=headB;
        int len=lenA-lenB;
        if(len<0){
            ps=headA;
            pl=headB;
            len=lenB-lenA;
        }
        while(len>0){
            len--;
            pl=pl.next;
        }
        while(pl!=null&&ps!=null&&pl!=ps){
            pl=pl.next;
            ps=ps.next;
        }
        if(pl==ps&&pl!=null){
            return pl;
        }
        return null;
    }
    

 

 
 
 
10. Dada una lista vinculada, determine si hay bucles en la lista vinculada.
Ideas: 1. Defina dos referencias, una para rápido y otra para lento, de modo que rápido da dos pasos a la vez y lento da un paso a la vez;
2. Rápido tiene que juzgar cada dos pasos, si se ha encontrado con lento.
 
 public boolean hasCycle(){
        //首先定义两个引用,让一个走一步,一个走两步
        Node fast=this.head;
        Node slow=this.head;
        while(fast!=null&&fast.next!=null){
            fast=fast.next.next;
            slow=slow.next;
            if(fast==slow){
                return true;
            }

        }
        return false;
    }

 

 
 
 
 
11. Dada una lista vinculada, devuelva el primer nodo donde la lista vinculada comienza a entrar en el anillo. Si la lista vinculada no tiene anillos, se devuelve un  valor nulo.
 
Ideas: 1. Similar a la idea de resolver si hay un bucle, es definir dos referencias, una rápida y otra lenta, rápida da dos pasos a la vez, lento da un paso a la vez, hasta que rápido = nulo o rápido.next = nulo fuera del bucle;
2. Después de saltar del bucle, determine el motivo de la salida. Si fast == null o fast.next == null, significa que no hay ningún anillo en la lista enlazada;
3. Si el bucle sale, el primer nodo del bucle debería resolverse ahora. como muestra la imagen:
 
 
 
public Node detectCycle(){
        Node fast=this.head;
        Node slow=this.head;
        while(fast!=null&&fast.next!=null){
            fast=fast.next.next;
            slow=slow.next;
            if(fast==slow){
                break;
            }
        }
        if(fast==null||fast.next==null){
            return null;
        }
        slow=this.head;
        while(slow!=fast){
            fast=fast.next;
            slow=slow.next;
        }
        return slow;

    }
    

 

 
 
 
 
 

 

 

 

Supongo que te gusta

Origin blog.csdn.net/m0_46551861/article/details/109538976
Recomendado
Clasificación