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:
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;
}
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.
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;
}
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}