首页 > 试题广场 >

链表中环的入口结点

[编程题]链表中环的入口结点
  • 热度指数:679279 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
给一个长度为n链表,若其中包含环,请找出该链表的环的入口结点,否则,返回null。

数据范围:
要求:空间复杂度 ,时间复杂度

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

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

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


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

输入

{1,2},{3,4,5}

输出

3

说明

返回环形链表入口结点,我们后台程序会打印该环形链表入口结点对应的结点值,即3   
示例2

输入

{1},{}

输出

"null"

说明

没有环,返回对应编程语言的空结点,后台程序会打印"null"   
示例3

输入

{},{2}

输出

2

说明

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

说明:本题目包含复杂数据结构ListNode,点此查看相关信息
推荐
如果链表中 有n个结点,指针P1在链表上向前移动n步,然后两个指针以相同的速度向前移动。
 当第二个指针指向环的入口结点时,第一个指针已经围绕着环走了一圈又回到了入口结点。
所以首先要得到环中结点的数目

public class 链表中环的入口结点 {
	//找到一快一满指针相遇处的节点,相遇的节点一定是在环中
	public static ListNode meetingNode(ListNode head) {
		if(head==null)
			return null;
		
        ListNode slow = head.next;
        if(slow==null)
        	return null;
        
        ListNode fast = slow.next;
        while (slow != null && fast != null) {
        	if(slow==fast){
        		return fast;
        	}
        	slow=slow.next;
        	fast=fast.next;
        	
        	if(fast!=slow){
        		fast=fast.next;
        	}
        }
		return null;
    }
	public ListNode EntryNodeOfLoop(ListNode pHead) {
		ListNode meetingNode=meetingNode(pHead);
		if(meetingNode==null)
			return null;
//		得到环中的节点个数
		int nodesInLoop=1;
		ListNode p1=meetingNode;
		while(p1.next!=meetingNode){
			p1=p1.next;
			++nodesInLoop;
		}
//		移动p1
		p1=pHead;
		for(int i=0;i<nodesInLoop;i++){
			p1=p1.next;
		}
//		移动p1,p2
		ListNode p2=pHead;
		while(p1!=p2){
			p1=p1.next;
			p2=p2.next;
		}
		return p1;
	}
}

编辑于 2015-08-25 11:27:14 回复(45)
我觉得可以用map解决
function EntryNodeOfLoop(pHead)
{
    // write code here
    if (pHead.next === null) return null
    const map = new Map()
    let currentNode = pHead
    while(currentNode) {
        if (map.has(currentNode)) return currentNode
        else map.set(currentNode, currentNode)
        currentNode = currentNode.next
    }
    return null
}


发表于 2021-11-18 09:47:45 回复(0)
/*function ListNode(x){
    this.val = x;
    this.next = null;
}*/
function EntryNodeOfLoop(pHead)
{
    // write code here
    if(!pHead){
        return null;
    }
    
    let key=0;
    let obj={};
    while(pHead){
       key = pHead.val;//节点值
       if(obj[key]){//已有节点,则有环,返回节点
           return pHead;
       }else{//没有,继续执行,数量为1
           obj[key]=1;
           pHead = pHead.next;
       }
    }
}
module.exports = {
    EntryNodeOfLoop : EntryNodeOfLoop
};

发表于 2021-11-14 16:48:33 回复(0)
function EntryNodeOfLoop(pHead)
{
    while(pHead !== null){
        if(pHead.flag){
            return pHead
        }else{
            pHead.flag = true;
            pHead = pHead.next
        }
    }
    return null
}

发表于 2021-10-03 13:46:04 回复(0)
function EntryNodeOfLoop(pHead)
{
    // write code here
    let fast =pHead;
    let slow =pHead;
    while(fast&&fast.next){
        fast=fast.next.next;
        slow=slow.next;
        if(fast==slow) break;
    };
    if(!fast||!fast.next) return null
    fast=pHead;
        while(fast!=slow){
        fast=fast.next;
        slow=slow.next;
    };
    return fast
}

发表于 2021-07-19 11:33:43 回复(0)
快慢指针判断是否有环,有环的情况下,慢指针从相遇点走,快指针从头走
function EntryNodeOfLoop(pHead)
{
    // write code here
    if(!pHead) return null 
    let fast = pHead, slow = pHead
    while(fast && fast.next){
        fast = fast.next.next
        slow = slow.next
        if(fast == slow){
            while(pHead !== slow){
                pHead = pHead.next
                slow = slow.next
            }
            return slow
        }
    }
    return null
}

发表于 2021-06-18 10:07:51 回复(0)
function EntryNodeOfLoop(pHead)
{
    // write code here
    var fast = pHead,
        slow = pHead;
    while(fast && fast.next){
        fast = fast.next.next;
        slow = slow.next;
        if(fast == slow){
            break;
        }
    }
    if(!fast || !fast.next){
        return null;
    }
    fast = pHead;
    while(fast != slow){
        fast = fast.next;
        slow = slow.next;
    }
    return fast;
}

发表于 2021-03-22 16:32:02 回复(0)
一次遍历完成:
遍历过的指针指向自己,直到遇到指向的节点证明是环入口
function EntryNodeOfLoop(pHead){
    // write code here
    if (!pHeadreturn null;
    while(pHead) {
        if (pHead.next == pHead) {
            return pHead
        }
        let tmp = pHead;
        pHead = pHead.next;
        tmp.next = tmp;
    }
    return null
}
发表于 2021-01-25 17:26:55 回复(0)
function EntryNodeOfLoop(pHead)
{
    // write code here
    if(!pHead){
        return null
    }
    let temp = pHead
    let arr = []
    while(temp){
        if(arr.includes(temp)){
            return temp
        }
        arr.push(temp)
        temp = temp.next
    }
    return null
}
  1. 遍历单链表的每个结点
  2. 如果当前结点地址没有出现在所定义的数组中,则存入该数组中
  3. 否则,就是出现在该数组中,则当前结点就是环的入口结点
  4. 整个单链表遍历完,若所有节点地址都没出现在数组中,则不存在环

编辑于 2020-07-20 11:02:50 回复(0)
/*function ListNode(x){
    this.val = x;
    this.next = null;
}*/
function EntryNodeOfLoop(pHead)
{
    // write code here
    let fast = pHead;
    let slow = pHead;
    while(fast && fast.next){
        fast = fast.next.next;
        slow = slow.next;
        if(fast == slow){
            fast = pHead;
            while(fast != slow){
                fast = fast.next;
                slow = slow.next;
            }
            return fast
        }
    }
    return null;
}

发表于 2020-02-08 11:55:59 回复(0)
/*function ListNode(x){
    this.val = x;
    this.next = null;
}*/
function EntryNodeOfLoop(pHead)
{
    // write code here
    if(!pHead) return null;
    let nodeList = [];
    let currNode = pHead;
    while(currNode !== null){
        if(nodeList.indexOf(currNode) !== -1){
            return currNode;
        }
        nodeList.push(currNode);
        currNode = currNode.next;
    }
    return null;
}

发表于 2019-09-17 23:54:53 回复(0)
/*function ListNode(x){
    this.val = x;
    this.next = null;
}*/
function EntryNodeOfLoop(pHead)
{
    // write code here
    let tmp = {}
    let p = pHead
    while(p) {
        if(!tmp[p.val]) {
            tmp[p.val] = 1
            p = p.next
        }else {
            return p
        }
    }
    return null
}

发表于 2019-09-16 17:35:05 回复(0)
function EntryNodeOfLoop(pHead)
{
    let h = pHead;
    if(!h.next || !h.next.next){
        return null;
    }
    let fast = h.next.next;
    let slow = h.next;
    while(fast!==null && fast.next!==null){
        if(fast === slow){
            fast = h;
            while(fast !==slow){
                fast=fast.next;
                slow=slow.next;
            }
            return slow;
        }else{
            fast = fast.next.next;
            slow = slow.next;
        }
    }
    return null;
}

发表于 2019-09-13 16:32:42 回复(0)
// 声明两个指针 P1 P2
// 1.判断链表是否有环: P1 P2 从头部出发,P1走两步,P2走一步,如果可以相遇,则环存在
// 2.从环内某个节点开始计数,再回到此节点时得到链表环的长度 length
// 3.P1、P2 回到head节点,让 P1 先走 length 步 , 当P2和P1相遇时即为链表环的起点

    function EntryNodeOfLoop(pHead) {
      if (!pHead || !pHead.next) {
        return null;
      }
      let P1 = pHead.next;
      let P2 = pHead.next.next;
      // 1.判断是否有环
      while (P1 != P2) {
        if (P2 === null || P2.next === null) {
          return null;
        }
        P1 = P1.next;
        P2 = P2.next.next;
      }
      // 2.获取环的长度
      let temp = P1;
      let length = 1;
      P1 = P1.next;
      while (temp != P1) {
        P1 = P1.next;
        length++;
      }
      // 3.找公共节点
      P1 = P2 = pHead;
      while (length-- > 0) {
        P2 = P2.next;
      }
      while (P1 != P2) {
        P1 = P1.next;
        P2 = P2.next;
      }
      return P1;
    }

发表于 2019-03-26 14:26:07 回复(0)
// 题目描述:一个链表中包含环,请找出该链表的环的入口结点。

/*function ListNode(x){
    this.val = x;
    this.next = null;
}*/

// 解题思路: 
// 1. 一个指针走一步,一个指针走两步,如果在到Null之前重合,则证明有环存在
// 2. 假设这个环走了若干个结点,但是由于要圈上 多走整数圈数 才能相遇,则这个等式成立 2x = x + r*n,r为圈数
// 3. 那么此时新建一个从头开始,走一步的指针,同时继续走,走x步即可回到相遇点,但是如果在相遇点之前重合,则重合点为入口
function EntryNodeOfLoop(pHead)
{
    if(!pHead || !pHead.next) {
      return null
    }
    let fast = pHead
    let slow = pHead
    // 题目已知有环
    while(1) {
      fast = fast.next
      slow = slow.next.next
      if(fast === slow) {
        break
      }
    }
    let result = pHead
    while(result !== slow) {
      slow = slow.next
      result = result.next
    }
    return result
}
编辑于 2018-02-23 11:58:03 回复(0)