IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> C++算法题:找环形单链表的环入口 -> 正文阅读

[数据结构与算法]C++算法题:找环形单链表的环入口

问题1:怎样才能检测到链表中存在循环?

书中给出的最终算法是定义两个指针p1,p2,p1每次移动一个位置,而p2每次移动两个位置,这样如果链表中存在循环,那么p2一定能追上p1。如果不存在,那么p2会到达链表尾部,即检测到空

//这个算法,并没有找到入口,而是找到了相遇点
bool hasCircle(Node* head, Node* &encounter)  
{  
    Node *fast = head, *slow = head;  
    while(fast && fast->next)  
    {  
        fast = fast->next->next;  
        slow = slow->next;  
        if(fast == slow)  
        {  
            encounter = fast;  
            return true;  
        }  
    }  
    encounter = NULL;  
    return false;  
}  

问题2:有一个单链表,其中可能有一个环,也就是某个节点的next指向的是链表中在它之前的节点,这样在链表的尾部形成一环。如果链表存在环,找到环的入口点?

第一种解法:

需要辅助空间,可以用散列表,用来存放结点的地址。(用散列表为O(n),而用集合为O(nlogn),而空间复杂度为O(n))

//运用集合set,没找到就插入,找到了,就是第二次相遇
//函数功能 : 找含单链表的环入口点  
//函数参数 : pHead指向链表首部  
//返回值 :   返回的是环的入口点,如果不存在环,返回NULL  
ListNode* FindFirstCrossNode_Solution1(ListNode * pHead)  
{  
    set<ListNode *> addrSet; //这里用集合代替散列,会影响时间复杂度   
    ListNode *pNode = pHead;  
    while(pNode != NULL)  
    {  
        if(addrSet.find(pNode) == addrSet.end())  
            addrSet.insert(pNode);  
        else  
            break;  
        pNode = pNode->next;  
    }  
    return pNode;  
} 

第二种解法:

容易想到的就是用穷举法,对于每个结点,检查该结点是否是环的入口点。

这种方法先让外循环走到相交点,内循环走到这个点,点相等距离不一样所以就是它。

ListNode* FindFirstCrossNode_Solution2(ListNode * pHead)  
{  
    ListNode *p1 = pHead;  
    int pos1 = 0;  
    while(p1)   //检查链表的每个结点  
    {  
        ListNode *p2 = pHead;  
        int pos2 = 0;  
        while(p2) //每次都从头开始  
        {  
            if(p1 == p2) //两个指针指向的结点一样,可能是相交也可能不相交  
            {  
                if(pos1 == pos2) //两个指针走过的距离一样  
                    break;  
                else  //p1在环中绕了一圈,导致pos1与pos2不一样  
                    return p1;   
            }  
            p2 = p2->next; //前进一个位置  
            pos2++;        //记录走过的距离  
        }  
        p1 = p1->next;  
        pos1++;  
    }  
    return NULL;  
}

最聪明,却又最简单的解法!!!

借用问题1找到的相遇点;相遇点到环入口,跟从Head开头到环入口,是一样的距离。(因为p2走的距离是p1的两倍,多走的是一部分圆和这个小尾巴)

Node* findEntry(Node* head, Node* encounter)  
{   
    Node *p1 = head, *p2 = encounter;  
    while(p1 != p2)  
    {  
        p1 = p1->next;  
        p2 = p2->next;  
    }  
    return p1;  
}

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-05-12 16:37:25  更:2022-05-12 16:38:27 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 4:53:30-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码