【力扣】判断环形链表

/*
 * **************************************************************************
 * ********************                                  ********************
 * ********************      COPYRIGHT INFORMATION       ********************
 * ********************                                  ********************
 * **************************************************************************
 *                                                                          *
 *                                   _oo8oo_                                *
 *                                  o8888888o                               *
 *                                  88" . "88                               *
 *                                  (| -_- |)                               *
 *                                  0\  =  /0                               *
 *                                ___/'==='\___                             *
 *                              .' \\|     |// '.                           *
 *                             / \\|||  :  |||// \                          *
 *                            / _||||| -:- |||||_ \                         *
 *                           |   | \\\  -  /// |   |                        *
 *                           | \_|  ''\---/''  |_/ |                        *
 *                           \  .-\__  '-'  __/-.  /                        *
 *                         ___'. .'  /--.--\  '. .'___                      *
 *                      ."" '<  '.___\_<|>_/___.'  >' "".                   *
 *                     | | :  `- \`.:`\ _ /`:.`/ -`  : | |                  *
 *                     \  \ `-.   \_ __\ /__ _/   .-` /  /                  *
 *                 =====`-.____`.___ \_____/ ___.`____.-`=====              *
 *                                   `=---=`                                *
 * **************************************************************************
 * ********************                                  ********************
 * ********************      				             ********************
 * ********************         佛祖保佑 永远无BUG        ********************
 * ********************                                  ********************
 * **************************************************************************
 */

目录

(一)题解:

判断环形链表 

        给定一个链表的头节点  head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

        如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

        不允许修改 链表。

示例 1:

【力扣】判断环形链表_第1张图片

输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

【力扣】判断环形链表_第2张图片

输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

输入:head = [1], pos = -1
输出:返回 null
解释:链表中没有环。

提示:

  • 链表中节点的数目范围在范围 [0, 10000] 内
  • -100000 <= Node.val <= 100000
  • pos 的值为 -1 或者链表中的一个有效索引

进阶:你是否可以使用 O(1) 空间解决此题?

(一)题解:

        ——不带环链表:这里不给出不带环链表的情况。

        ——带环链表:画图表示一个带环链表 

 

【力扣】判断环形链表_第3张图片 

 

        使用快慢指针法:

       创建快慢指针->

        快指针:fast

        慢指针:slow 

        创建快慢指针。由于快指针每次走两步,慢指针每次走一步,所以当快指针走到环起始节点时,慢指针还在环前单链表的半程位置:

【力扣】判断环形链表_第4张图片

        当慢指针进入环时,快指针已经在环中走了一会儿了。

 【力扣】判断环形链表_第5张图片

        我们设此时快慢指针之间的距离为D(distance),单串链表长度为L,环形链表的周长为C,则另一半优弧的长度为C-D,由于快慢指针都在绕圈,于是这个问题就演变成了追及问题。

(这里暂且把节点数称为长度) 

 【力扣】判断环形链表_第6张图片

        由于快指针每次走两步,慢指针每次走一步,快慢指针的速度差为1,那么不论D是什么值,每次两指针间的距离减小1,于是距离为D,D-1,D-2,D-3……2,1,0(追上)。

         最终追上:

【力扣】判断环形链表_第7张图片

由于速度差\Deltav是 常数1,1是任何数的因子,所以D一定可以平缓的逐渐减小到0,减小到0就意味着追上了。这样就解释清楚了为什么快2慢1一定可以追上。 

       

 对于整个过程:

slow的路程 = L + X;

fast的路程 = L + n*C + X

得到等式: 

 slow的路程*2=fast的路程->:2*(L+X) = L + n*C + X

化简得:

L = n*C - X

不妨设:n等于1;

L = n - X

         那么,环形链表中剩余的节点数就等于L的节点数,我们就可以在找到相遇节点后用meet指针记录下来,接下来用判断链表相交的方法来找到环的第一个节点:

代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
 typedef struct ListNode LS;
struct ListNode *detectCycle(struct ListNode *head) {
    LS *fast = head;
    LS *slow = head;
    
    int f = 0;
    while(fast && fast->next)
    {
        fast = fast ->next ->next;
        slow = slow->next;
        if(fast == slow)
        {
            LS* meet = slow;
            while(meet != head)
            {
                meet = meet->next;
                head = head->next;
            }
            return meet;
        }
    }
    return NULL;
}

完~

未经作者同意禁止转载

你可能感兴趣的:(决胜oj,leetcode,链表,算法)