判断单链表是否有环

  1. 1 问题
  2. 2 思路一
  3. 3 思路二

1 问题

给定一个单链表,判断是否存在环;

2 思路一

从第一个节点开始遍历链表,并用map<Node*, int>(key为遍历到的节点,val表示节点的顺序递增编号)保存遍历到的节点,在遍历到当前节点时:
查询map,当前节点是否已经在map中,如查询到则说明有环;如没查询到则编号递增,将当前节点插入map;
遍历至NULL,则说明链表无环;
链表有环,则第一个在map中查到的节点必定是环的入口节点,节点的最大编号 - 入口节点编号 + 1 = 环的长度,入口节点编号 - 1 - 非环部分长度;

bool hasCircle(Node* n, int& circle_len, int& non_circle_len)
{
    int no = 0;
    map<Node*, int> nodes;
    map<Node*, int>::const_iterator iter;
    while(n)
    {
        iter = nodes.find(n);
        if(iter == nodes.end())
        {
            no++;
            node[n] = no;
        }
        else
        {
            break;
        }
        n = n->next;
    }

    if(n)
    {
        circle_len = no - iter->second + 1;
        non_circle_len = iter->second - 1;
        return true;
    }
    else
    {
        circle_len = 0;
        non_circle_len = no;
    }
    return false;
}

3 思路二

一个快指针和慢指针同时从第一个节点出发,快指针每次走两步,慢指针每次走一步;如果有环,则快慢指针必定相遇。
设非环部分长度为$L_1$,环长为$L_2$,第一个入环节点为$N$,慢指针走$s$步后快慢指针相遇,则相遇点$r$满足:
(s-$L_1$)$\equiv$r mod($L_2$)
(2s-$L_1$)$\equiv$r mod($L_2$)
则:
s$\equiv$0 mod($L_2$)
即$L_2$ | $s$时,快慢指针相遇,代入得相遇点为$r$=$t$$L_2$ - $L_1$,其中$t$为整数,此时放一个慢指针在链表初始位置,一个慢指针在相遇点,两指针同时出发,则必相遇于环的入口点。

bool hasCircle(Node* n, int& circle_len, int& non_circle_len)
{
    Node *slow = n, *fast = n, *slow2 = n;
    non_circle_len = 0, circle_len = 0;

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

        if(slow == fast)
        {
            break;
        }
    }

    if(!fast || !fast->next)
    {
        circle_len = 0;

        if(fast) non_circle_len++;
        return false;
    }

    non_circle_len = 0;
    while(true)
    {
        non_circle_len++;
        slow = slow->next;
        slow2 = slow2->next;
        if(slow == slow2)
        {
            break;
        }
    }

    while(true)
    {
        non_circle_len++;
        slow = slow->next;
        if(slow == slow2)
        {
            break;
        }
    }

    return true;
}

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至yj.mapple@gmail.com

文章标题:判断单链表是否有环

文章字数:519

本文作者:melonshell

发布时间:2020-01-15, 08:18:04

最后更新:2020-01-17, 15:47:15

原始链接:http://melonshell.github.io/2020/01/15/ds_link_list_circle/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录
×

喜欢就点赞,疼爱就打赏

相册