Puntero de velocidad
Directorio de artículos
- Puntero de velocidad
-
- Patrón común
- La primera lista circular vinculada
- La segunda lista circular vinculada
- ¡El nodo del medio de la tercera lista vinculada! [Inserte la descripción de la imagen aquí] (https://img-blog.csdnimg.cn/20200401153500367.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGkshadow_10,text_aHR0cHM9n= , tamaño_16, color_FFFFFF, t_70)
- La cuarta forma es eliminar el n-ésimo nodo de la parte inferior de la lista vinculada
Patrón común
En relación con la lista
vinculada , determine si la lista vinculada tiene bucles, etc.
La primera lista circular vinculada
Ideas:
Si la lista vinculada es una lista vinculada circular, entonces podemos definir dos punteros, uno avanza dos nodos a la vez y el otro avanza un nodo a la vez. Esto es lo mismo que la competencia de pista y campo. Si los dos atletas corren en línea recta, el atleta rápido y el atleta lento están en la misma posición en el punto de partida, pero el atleta rápido llegará primero al final, durante el cual los dos atletas no Reunirse. Y si corres en círculos (asumiendo que no hay límite en la cantidad de metros), los atletas rápidos se encontrarán cuando superen en una vuelta a los atletas lentos.
La diferencia con la tortuga y la liebre:
En cuanto a la velocidad de los dos punteros en los punteros rápido y lento: a diferencia de la carrera de la tortuga y la liebre, la carrera de la tortuga y la liebre es un problema de continuidad. No importa cuánto sea la diferencia de velocidad entre los dos, se puede suponer lo siguiente: suponiendo que la longitud de la pista es s, v_f representa el valor de la velocidad rápida, v_s representa el valor de la velocidad lenta (asumiendo que las posiciones iniciales de los dos son iguales), entonces puede encontrar: (v_f-v_s) t = s; el t calculado de esta manera es la primera vez que los dos se encuentran La diferencia en esta pregunta es: para la lista vinculada, es un valor discreto. Suponemos que hay n nodos en el anillo. También asumimos que el puntero rápido y el puntero lento son v_f y v_s respectivamente; si desea reunirse (asumiendo la misma posición inicial) , También tenga (v_f-v_s) k = n; ——En este momento v_f, v_s son enteros positivos, k es el número de ciclos y n es el número de nodos; k = n / (v_f-v_s) Si quiere que k sea un número entero, entonces Se puede ver que la diferencia de velocidad entre los dos es requerida, y debe ser divisible por n; Nota: Esta es la primera vez que se encuentra, y también es posible que v_f-v_s sea un múltiplo entero de n;
Código:
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public boolean hasCycle(ListNode head) {
if(head==null)
return false;
ListNode p=head;
ListNode q=head;
while(p!=null&&q!=null)
{
p=p.next;
if(q.next==null)
return false;
q=q.next.next;
if(p.equals(q))
{
return true;
}
}
return false;
}
}
La segunda lista circular vinculada
Ideas:
Como se muestra en la figura, suponga que hay un nodo
en un no anillo yb nodos en un anillo
.
fast走的节点数=2*slow走的节点数\\
fast走的节点数-slow走的节点数=nb(多走了n圈)
第一次相遇时slow走的节点数为nb
一个节点走a+nb步一定会在入口处
slow在第一次相遇后再走a步即可
可以第一次相遇后,设置一个指针从头开始,以slow的速度,两者相遇时即为入口
Código:
public class Solution {
public ListNode detectCycle(ListNode head) {
if(head==null)
return null;
ListNode p=head;
ListNode q=head;
if(head.next==null)
{
return null;
}
while(p!=null&&q!=null)
{
p=p.next;
if(q.next==null)
return null;
q=q.next.next;
if(p.equals(q))
{
q=head;
while(p!=null&&q!=null)
{
if(p.equals(q))
{
return p;
}
q=q.next;
p=p.next;
}
}
}
return null;
}
}
El nodo medio de la tercera lista vinculada
Ideas:
El puntero rápido cruza dos nodos a la vez; el
puntero lento cruza un nodo a la vez; cuando el
puntero rápido llega al final, el puntero lento llega a la posición media.
Código:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode middleNode(ListNode head) {
ListNode fast=head;
ListNode slow=head;
while(true)
{
if(fast.next==null)
{
return slow;
}
if(fast.next.next==null)
{
slow=slow.next;
return slow;
}
else {
fast=fast.next.next;
slow=slow.next;
}
}
}
}
La cuarta forma es eliminar el n-ésimo nodo de la parte inferior de la lista vinculada
Ideas:
El puntero rápido
pasa por n nodos primero, y luego los punteros rápido y lento bajan un nodo
a la vez. Cuando el puntero rápido llega al final,
la posición alcanzada por el puntero lento es el último nodo
Código:
public static ListNode deleteNode(ListNode head,int n) {
ListNode p=head;
ListNode q=head;
for(int i=0;i<n-1;i++)
{
p=p.next;
}
while(true)
{
if(p.next.next==null)
{
q.next=q.next.next;
return head;
}
p=p.next;
q=q.next;
}
}