lista enlazada circular
1. Tema
Enlace: 141. Lista circular enlazada I
2. Ideas
3. Código
bool hasCycle(struct ListNode *head) {
struct ListNode*slow = head;//慢指针
struct ListNode*fast = head;//快指针
while(fast&&fast->next)//快指针所指向的节点和快指针的下一个节点都不为空的时候才向后执行
{
slow = slow->next;//慢指针一次走一步
fast = fast->next->next;//快指针一次走两步
if(slow==fast)//当慢指针追上快指针时停下,说明是带环链表
return true;
}
return false;//慢指针没有追上快指针式
}
4. Ampliar la pregunta
Pregunta extendida 1
1. Lento da un paso a la vez y rápido da 2 pasos a la vez. ¿Puedes alcanzarlo? Por favor prueba.
Debe ser capaz de ponerse al día.
Pregunta extendida 2
2. Lento da 1 paso a la vez y rápido da 3 pasos a la vez. ¿Puedes alcanzarlo? rápido ¿qué tal 4 pasos a la vez? ¿Qué pasa con n pasos? Por favor prueba.
No necesariamente, ¡es posible que nunca se ponga al día en escenarios especiales!
Otro razonamiento sobre dar 4 pasos y n pasos a la vez es similar al anterior.
Discutamos la situación cuando rápido da 4 pasos a la vez.
Pregunta extendida 3
3. Solicite el punto de entrada del anillo de listas enlazadas. Devuelve NULL si la lista enlazada no tiene bucles.
Esta pregunta es en realidad la pregunta número 142 de leetcode. ¡Echémosle un vistazo!
tema
Enlace: 142. Lista Circular Enlazada II
ideas
Dos métodos:
Idea 1
1. Prueba de fórmula
Código:
struct ListNode *detectCycle(struct ListNode *head) {
struct ListNode*slow = head;
struct ListNode*fast = head;
while(fast&&fast->next)
{
slow = slow->next;
fast = fast->next->next;
if(slow==fast)
{
struct ListNode*meet = slow;//记录下相遇的节点
while(meet!=head)//meet节点与head节点同时开始走,相遇点
{
meet = meet->next;
head = head->next;
}
return meet;
}
}
return NULL;
}
Idea 2
2. Abra la lista vinculada para la conversión
A través del método anterior, el problema se transforma en el problema de encontrar los nodos de intersección de la lista enlazada de intersección.
Nota: En el siguiente código, headB es meet->next y headA es head. Vale la pena señalar que después de asignar meet->next a headB ,No olvides asignar meet->junto a un puntero nulo.
Código:
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {//复用的是找相加节点的代码
struct ListNode*tailA = headA;//记录链表A的尾节点
struct ListNode*tailB = headB;//记录链表B的尾节点
int lenA = 1;//记录链表A的长度
int lenB = 1;//记录链表B的长度
while(tailA->next!=NULL)
{
tailA = tailA->next;
lenA++;
}
while(tailB->next!=NULL)
{
tailB = tailB->next;
lenB++;
}
if(tailA!=tailB)//尾节点不等,所以直接返回NULL
{
return NULL;
}
//相交,求节点,长的先走差距步,再同时走找交点
struct ListNode*shortList = headA,*longList = headB;//默认A是较长节点的链表,B是较短的
if(lenA>lenB)
{
longList = headA;
shortList = headB;
}
int gap = abs(lenA - lenB);//gap存储的是节点数的差值
while(gap--)
{
longList = longList->next;//节点数多的先走gap步
}
while(longList!=shortList)//两者同时开始进行遍历,在交点处停下
{
longList = longList->next;
shortList = shortList->next;
}
return longList;//随便返回一个就行,因为两个都是交点
}
struct ListNode *detectCycle(struct ListNode *head)
{
struct ListNode*slow = head;
struct ListNode*fast = head;
while(fast&&fast->next)
{
slow = slow->next;
fast = fast->next->next;
if(slow==fast)
{
struct ListNode*meet = slow;//记录下相遇的节点
struct ListNode*headB = meet->next;
struct ListNode*headA = head;
meet->next = NULL;
struct ListNode*ret = getIntersectionNode(headA,headB);//返回的节点存储在ret中
return ret;
}
}
return NULL;
}