美文网首页
算法进阶——链表中环的入口节点

算法进阶——链表中环的入口节点

作者: 拉普拉斯妖kk | 来源:发表于2023-11-19 10:50 被阅读0次

题目


给一个长度为n链表,若其中包含环,请找出该链表的环的入口结点,否则,返回null。

数据范围:1<=结点值<=10000

要求:空间复杂度O(1),时间复杂度O(n)

例如,输入{1,2},{3,4,5}时,对应的环形链表如下图所示:

可以看到环的入口结点的结点值为3,所以返回结点值为3的结点。

输入描述:

输入分为2段,第一段是入环前的链表部分,第二段是链表环的部分,后台会根据第二段是否为空将这两段组装成一个无环或者有环单链表。

返回值描述:

返回链表的环的入口结点即可,我们后台程序会打印这个结点对应的结点值;若没有,则返回对应编程语言的空结点即可。

示例1

输入:
{1,2},{3,4,5}
返回值:
3
说明:
返回环形链表入口结点,我们后台程序会打印该环形链表入口结点对应的结点值,即3 

示例2

输入:
{1},{}
返回值:
"null"
说明:
没有环,返回对应编程语言的空结点,后台程序会打印"null"

示例3

输入:
{},{2}
返回值:
2
说明:
环的部分只有一个结点,所以返回该环形链表入口结点,后台程序打印该结点对应的结点值,即2

思路


首先,题目中给的链表并不一定是有环的,所以需要先判断链表是否有环。可以在通过快慢指针的方式来判断,如果有环,则可以计算出环节点的个数。

然后,定义两个指针初始化指向头节点,第一个指针先前进环节点个数,之后两个节点同时前进,到节点值相等的节点就是环的入口节点。

本题还可以使用哈希表unordered_set来记录经过的节点来解决,但是这个方法的空间复杂度时O(n)。

另外,我的解法写的比较复杂,主要是为了理顺思路。使用快慢指针可以用更简洁的代码解决。

解答代码


/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead) {
        if (pHead == nullptr || pHead->next == nullptr) {
            return nullptr;
        }

        // 获取到环节点的个数
        int loop_node_num = GetLoopNodeNum(pHead);
        if (loop_node_num == 0) {
            // 链表中没有环
            return nullptr;
        }

        ListNode* pNode1 = pHead;
        ListNode* pNode2 = pHead;
        // 第一个节点先前进loop_node_num步
        for (int i = 0; i < loop_node_num; i++) {
            pNode1 = pNode1->next;
        }

        // 两个节点同时前进
        while (pNode1->val != pNode2->val) {
            pNode1 = pNode1->next;
            pNode2 = pNode2->next;
        }

        // 相等的点就是环的入口
        return pNode1;  
    }

    int GetLoopNodeNum(ListNode* pHead) {
        int loop_node_num = 0;
        // 定义快慢指针
        ListNode* fast = pHead->next;
        ListNode* slow = pHead;

        // 判断是否有环
        bool is_loop = false;
        while (fast != nullptr) {
            if (fast->val == slow->val) {
                is_loop = true;
                break;
            } else {
                if (fast->next != nullptr) {
                    fast = fast->next->next;
                    slow = slow->next;
                } else {
                    break;
                }
            }
        }

        // 有环,则步进慢指针计算环的节点数
        if (is_loop) {
            int val = slow->val;
            loop_node_num = 1; // 加上自身
            while (val != slow->next->val) {
                ++loop_node_num;
                slow = slow->next;
            }
        }

        return loop_node_num;
    }
};

相关文章

  • 链表中环的入口节点

    题目描述 给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。 思路 首先是判断链表中是否有...

  • 链表中环的入口节点

    给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。 解法1: 新建一个HashSet,遍历...

  • 链表中环的入口节点

    题目描述 一个链表中包含环,请找出该链表的环的入口结点。 解法一: 要想知道环的入口节点,则必须至少经过该节点两次...

  • 链表中环的入口节点

    题目描述 给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。 第一想法 通过指针地址是否出...

  • 链表中环的入口节点

  • 链表中环的入口节点

    《剑指offer》面试题23:链表中环的入口节点 题目:给一个链表,若其中包含环,请找出该链表的环的入口结点,否则...

  • 链表中环的入口节点

    题目:如果一个链表中包含环,如何找出环的入口节点? 解决这个问题的第一步是如何确定一个链表中包含环。定义两个指针,...

  • 剑指 offer:55、链表中环的入口节点

    55. 链表中环的入口节点 题目描述 给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。 ...

  • 23:链表中环的入口节点

    习惯github pages风格的请看我的另一篇博客 题目23:链表中环的入口节点 如果一个链表中包含环,请找出该...

  • 面试题23(剑指offer)--链表中环的入口节点

    题目: 给一个链表,若其中包含环,请找出该链表的环的入口结点。 思路: �链表中环的入口节点 先确定有环,用快慢指...

网友评论

      本文标题:算法进阶——链表中环的入口节点

      本文链接:https://www.haomeiwen.com/subject/bezpwdtx.html