环形链表入口节点

环形链表入口节点

题目描述

思路分析:判断是否有环

本题是判断环形链表是否有环的进阶题目。

环形链表题目利用了双指针技巧,设置快慢两个指针,每次快指针走两步慢指针走一步。假如链表有环,那么快慢指针在环的部分终究会相遇。

判断链表是否有环,比较简单直接上代码。

public boolean hasCycle(ListNode head) {
        if (head == null || head.next == null) {
            return false;
        }
        ListNode slow = head;
        ListNode fast = head;
        while (fast.next != null && fast.next.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            if (slow == fast) {
                return true;
            }
        }
        return false;
    }

思路分析:如何找出入口节点?

方便分析作图如下,假设a是链表头节点,b是链表中环的入口节点,c是快慢指针相遇的节点。

三段路径长度按顺时针分别称为ab,bc,cb。链表中环长度为s = bc + cb。

我们需要计算,在c点相遇的时候,快慢指针分别走了多远?利用快慢指针长度的两倍关系去求解问题。

快指针到c点走过的长度 s1 = ab + bc + n * s = ab + bc + n * (bc + cb)

快指针走的距离包括ab+bc的距离,再加上在圆环中环绕圈数的距离。

那么慢指针的长度如何计算?他在环中也走了多少圈?

这就需要理解一个概念:

从慢指针进入环时,到快慢指针相遇,慢指针走过的距离是一定小于等于环的大小。(如果整个链表是一个环,则慢指针走过距离等于环大小)
慢指针进入环后,可以看成快指针在后面追赶慢指针。

  • 最好情况快指针就在b的左侧,移动一步两者便相遇。
  • 最差情况为快指针在b的右侧,需要多绕不到一圈的距离。

分析最差情况:假设慢指针走了一整圈环,回到b点时快指针才追上,慢指针移动长度为s,快指针移动长度则为2s-1。但实际上快指针速度是慢指针两倍,即实际应走距离为2s。可以反证出在慢指针走完一圈之前,快指针必然追上慢指针。

理解了上述概念,可以很快得出,慢指针长度 s2 = ab + bc

已知了快指针是慢指针两倍,即 2 (ab + bc) = ab + bc + n (bc + cb)

推出:ab = (n-1) * (bc + cb) + cb

含义为:链表头到环入口的距离=相遇点到环入口的距离+(n-1)圈环长度

分析到这里,其实已经得出答案了。两个链表相遇后,一个指针指向相遇的位置,一个指针指到链表的头节点。两个指针均向后移动,判断当两者相同时,该节点便是链表到环的入口节点。

代码参考:

 public ListNode detectCycle(ListNode head) {
        if (head == null) {
            return null;
        }

        // 步骤一:使用快慢指针判断链表是否有环
        ListNode fast = head;
        ListNode slow = head;
        boolean hasCycle = false;
        while (fast.next != null && fast.next.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            if (slow == fast) {
                hasCycle = true;
                break;
            }
        }

        // 步骤二:若有环,找到入环开始的节点
        if (hasCycle) {
            ListNode cur = head;
            while (slow != cur) {
                cur = cur.next;
                slow = slow.next;
            }
            return slow;
        }

        return null;
    }

公众号:编程呓语,分享原创优质技术文章,欢迎大家关注。

原文地址:https://www.cnblogs.com/icecrea/p/12059619.html

时间: 2024-10-09 02:44:00

环形链表入口节点的相关文章

链表(13)----判断链表是否有环,并返回环入口节点

1.链表定义 typedef struct ListElement_t_ { void *data; struct ListElement_t_ *next; } ListElement_t; typedef struct List_t_{ int size; int capacity; ListElement_t *head; ListElement_t *tail; } List_t; 2.判断链表是否有环,并返回链表入口节点 (1)方法一:根据相遇节点.头结点.入口节点之间的距离关系求解

二叉树转换为双向环形链表

二叉树的节点与双向环形链表的节点类似,均含有两个指向不同方向的指针,因此他们之间的转化是可以实现的.下面介绍一种递归的实现方法.由于方法比较简单,就直接上代码了 二叉树的建立 node* create(const string& s) { node* res = new node; res->left = nullptr; res->right = nullptr; res->s = s; return res; } node* insert(node* root, const

56 - 链表中环的入口节点

题目: 一个链表中包含环,如何找出环的入口节点? 例如 1->2->3->4->5->6->(3) ; 的链表中,环的入口及诶到哪是节点 3. 解析: 首先找到链表中的环:定义2个指针,一个快指针一次走2步,一个慢指针一次走1步,如果2个指针能够相遇,证明有环. 统计链表中环的长度:从相遇指针开始,固定 1 个指针,另一个指针从相遇指针走,当2个指针再次相遇时,即走了 1 圈,得到环的长度 len. 2个指针指向链表开头,1个指针先走 len 步,另一个指针从头和前一个

数据结构和算法设计专题之---判断单链表中是否有环,环的长度,环的入口节点

题目: 给定一个单链表,只给出头指针head: 1.如何判断是否存在环? 2.如何知道环的长度? 3.如何找出环的连接点在哪里? 4.带环链表的长度是多少? 解法: 1.对于问题1,使用追赶的方法,设定两个指针slow.fast,从头指针开始,每次分别前进1步.2步.如存在环,则两者相遇:如不存在环,fast遇到NULL退出. 2.对于问题2,记录下问题1的碰撞点p,slow.fast从该点开始,再次碰撞所走过的操作数就是环的长度s. 3.问题3:有定理:碰撞点p到连接点的距离=头指针到连接点的

笔试算法题(27):判断单向链表是否有环并找出环入口节点 & 判断两棵二元树是否相等

出题:判断一个单向链表是否有环,如果有环则找到环入口节点: 分析: 第一个问题:使用快慢指针(fast指针一次走两步,slow指针一次走一步,并判断是否到达NULL,如果fast==slow成立,则说明链表有环): 第二个问题:fast与slow相遇时,slow一定还没有走完一圈(反证法可证明):  示意图A为起始点,B为环入口点,C为相遇点,则a1=|AB|表示起始点到换入口的距离,a2=|CB|表示相遇点到环入口点的距离,s1=|AB|+|BC|表示slow指针走的长度,s2表示fast指针

C++实现查找链表中环的入口节点

/* * 寻找链表中环的入口节点.cpp * * Created on: 2018年4月10日 * Author: soyo */ #include<iostream> using namespace std; struct Node{ int num; Node * next; }; Node * creat() { Node *head; Node *p; head=new Node; p=head; p->num=10; p->next=NULL; return head;

剑指offer(二十三,二十四,二十五)最小的k个数,连续子数组的最大和,链表中环的入口节点

23:最小的k个数 题目描述 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. 简单题.... function GetLeastNumbers_Solution(input, k) { if(k>input.length) return []; let ans = []; input = input.sort(); //console.log(input.join("").slice(0,4).split

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

题目描述给一个链表,若其中包含环,请找出该链表的环的入口节点,否则,输出null. # -*- coding: utf-8 -*- # @Time : 2019-04-23 22:40 # @Author : Jayce Wong # @ProjectName : job # @FileName : entryNodeOfLoop.py # @Blog : https://blog.51cto.com/jayce1111 # @Github : https://github.com/SysuJa

【LeetCode每天一题】 Intersection of Two Linked Lists(两个链表的入口节点)

Write a program to find the node at which the intersection of two singly linked lists begins. For example, the following two linked lists: begin to intersect at node c1. Example 1: Input: intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5],