【链表问题】单向链表判断是否有环、求入环节点、求环长、求链表长度

目录

 

题目:

思路:

代码实现

注意点

此题的其他变式


题目

判断一个单项链表是否有环,如果有环,返回入环节点的值,如果无环,返回-1.要求空间复杂度为O(1).

思路

空间复杂度如果没有要求, 可以用哈希表来判断。

在空间复杂度为O(1)的情况下,环状链表相关问题通常用快慢指针来辅助完成

快指针从头节点开始一次走两步,慢指针从头节点开始一次走一步。如果快指针为空或者快指针的next指针指向节点为空,则链表无环。

如果快指针和慢指针相遇,则链表有环。

在有环的情况下,我们找入环节点。

设环的周长为C,在相遇时,慢指针走的长度为

则快指针一定比慢指针多走(n = 0,1,2...) 的长度,

根据快慢指针的速度关系(快指针一次走两步,慢指针一次走一步),在相遇的时刻,有

由上面三个式子可得.

快慢指针相遇后,让快指针指向头部,慢指针不动。快指针一次走一步,慢指针一次走一步。

当快指针走长度时,慢指针走长度,此时两指针在入环节点处相遇。

代码实现
 

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class ChkLoop {
public:
    int chkLoop(ListNode* head) {
        // write code here
       if(head == NULL || head->next == NULL)
           return -1;
       ListNode *fast = head;
       ListNode *slow = head;
       while(fast!=NULL && fast->next!= NULL){//注意边界条件
          fast= fast->next->next;
          slow = slow->next;
          if(fast==slow){//有环,第一次相遇
             fast = head;//fast指针到链表头
             while(fast!=slow){
             fast = fast->next;
             slow = slow->next;
             }
             return  fast->val;
          }
       }
       return -1;
       
    }
};

注意点

1、边界条件的处理,判断快指针到达链表末尾的条件为fast == NULL ||  fast->next == NULL,因为在这两种情况下fast都不能继续往下走了。

2、函数开头对明显的空链表和只有一个节点的链表进行处理。

此题的其他变式

1、求单链表的环长

快慢指针第一次相遇后,继续快指针一次两步,慢指针一次一步,这样就变成了追及问题。从第一次相遇时刻到到第二次相遇时刻,快指针走的长度比慢指针多一圈。

2、判断有环单链表的长度

环长+头结点到入环节点的长度(lenA)

 

展开阅读全文

没有更多推荐了,返回首页