环形链表的题目

环形链表的题目:

第一个是判断里面是否有环;

第二是找环在那里,返回环的位置。

第一个题目:判断环

思路:

我们可以定义一个快慢指针,我们的快指针一次走两步,满指针一次走一步,当我们的快慢指针都指向同一个地方时就是我说明我们的链表有环。

解析:

当我们的指针都入环了,假设他们的距离差是n那每走一次,两个指针的距离就减少1,南无最后不管n是奇数还是偶数就都会相遇,

代码: 

 这个题目的代码很简单:

typedef struct ListNode Node;
bool hasCycle(struct ListNode *head) {
   Node* slow = head;
   Node* fast = head;

  while(fast && fast->next)
  {
    slow = slow->next;
    fast = fast->next->next;

    if(slow == fast)
      return true;
  }

  return false;
}

 

若走更多的步数行不行?

那这里还有一个疑问我们走三步.四步等等可不可以呢?

 这里就需要我们去进行计算了,当我们一次走三步时,当他们入环的时候呢,他们每次距离就缩小两步;那我们这里就有一个问题了,当他们之间的差距是偶数时,那么在第一圈的时候就会追上,但是当他是奇数的时候就会他们直间的距离就会变成一个-1,快指针就会超过慢指针,刚刚好错过了。

那么继续发生第二次追及,那么我们来思考一下第二次追击会不会追上,他们两个的距离就会变成环的长度减一,如果我们的环的长度是C,如果C-1是奇数那就永远追不上,C-1是偶数那就可以追上。

我们就要来验证一下这个第二种可能出现吗? 

我们发生第二种情况的是当他们都入环的时候距离位N,N这个时候是奇数,而且我们的C-1也是奇数,即C是偶数,这种情况存不存在。

 我们可以通过他们的路程的来写出一个等式,我们等式的左边是一个偶数那么我们的右边计算的结果也要是偶数,那我们偶数减偶数就是偶数,奇数减奇数也偶数。

所以当我们的N是奇数时C也是奇数,不会出现我们的N是奇数,C是偶数。

所以他最后还是会追上的,只是不会在第一圈追到,最后还是会追到的。

同理当我们的快指针走4步的时候,就会出现C-1和C-2这两种情况。C-2的也和我们的一样

结论:

第二个题:找环 

 

 思路:

我们也是利用快慢指针来写,我们先来找到我们快慢指针相遇的地方,然后我们在一个指针从相遇的地方开始走,一个从头节点开始走,两个指针同时开始走,他们再次相遇的地方就是入环的节点

解析

我们的环的长度为C;我们入环前的长度是L,当我们两个指针相遇时,假设在环里面走了N,那么我们再让一个从开头走,一个从相遇的节点走,我们可以通过等式来证明:

我们不知道我们入环之前的距离是多少,可能会很长,也可能会很短,所以可能在他们相遇之前,那个快指针就走了x圈。 

这里我们就能得出我们最后让两个指针,一个从相遇点开始走一个从头结点开始走,最后他们相遇的就是我们的入环节点。

代码:

typedef struct ListNode Node;
struct ListNode *detectCycle(struct ListNode *head) {
    	Node* slow = head;
        Node* fast = head;

        while(fast && fast->next)
        {
            slow = slow->next;
            fast = fast->next->next;
            //走到相遇点
            if(slow == fast)
            {
                // 求环的入口点
                Node* meet = slow;
                Node* start = head;

                while(meet != start)
                {
                    meet = meet->next;
                    start = start->next;
                }

                return meet;
            }
        }

        return NULL;
}

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

.小董

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值