列表

详情


BM7. 链表中环的入口结点

描述

给一个长度为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

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 2ms, 内存消耗: 536KB, 提交时间: 2020-12-14

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

Go 解法, 执行用时: 2ms, 内存消耗: 848KB, 提交时间: 2021-08-04

package main

func EntryNodeOfLoop(pHead *ListNode) *ListNode{
    if pHead == nil || pHead.Next == nil {
        return nil
    }
    // 快慢指针
    fast := pHead
    last := pHead
    
    for fast != nil && fast.Next != nil {
        fast = fast.Next.Next
        last = last.Next
        if fast == last {
            break
        }
    }
    // 第一次相遇
    if last == nil || fast == nil {
        // 无环
        return nil
    }
    last = pHead
    for last != fast {
        last = last.Next
        fast = fast.Next
    }
    return last
}

Go 解法, 执行用时: 2ms, 内存消耗: 852KB, 提交时间: 2021-08-06

package main

func EntryNodeOfLoop(pHead *ListNode) *ListNode{
    if (pHead == nil) {
        return nil
    }
    slow, fast := pHead, pHead
    var b bool
    for slow != nil && fast != nil && fast.Next != nil {
        slow = slow.Next
        fast = fast.Next.Next
        if (slow == fast) {
            b = true
            break
        }
    }
    if (!b) {
        return nil
    }
    fast = pHead
    for fast != slow {
        fast = fast.Next
        slow = slow.Next
    }
    return fast
}

Go 解法, 执行用时: 2ms, 内存消耗: 928KB, 提交时间: 2021-03-06

package main

/*
 * 思路:首先判断链表是否有环,方法是快慢指针;
 * 接下来计算链表环中有多少个结点(count),方法是选定环中的一个结点然后计数,直到再次回到当前结点;
 * 最后是找到链表环的入口结点,方法是双指针,一个指针先走count步,然后以相同的速度往前走,
 * 最终两个指针将在链表环的入口处相遇;
 */
func EntryNodeOfLoop(pHead *ListNode) *ListNode {
	markNode := HasLoop(pHead)
	if markNode == nil {
		return nil
	}
	count := CountNodesInLoop(markNode)
	slow := pHead
	fast := pHead
	for i := 0; i < count; i++ {
		fast = fast.Next
	}
	for slow != fast {
		slow = slow.Next
		fast = fast.Next
	}
	return slow
}

// 判断链表是否有环,有环则返回环中的节点,否则返回nil
func HasLoop(pHead *ListNode) *ListNode {
	if pHead == nil {
		return nil
	}
	slow := pHead
	fast := pHead
	for fast.Next != nil && fast.Next.Next != nil {
		slow = slow.Next
		fast = fast.Next.Next
		if slow == fast {
			return slow
		}
	}
	return nil
}

// 计算链表环中节点的个数
func CountNodesInLoop(markNode *ListNode) int {
	cur := markNode.Next
	count := 1
	for cur != markNode {
		count++
		cur = cur.Next
	}
	return count
}

Go 解法, 执行用时: 2ms, 内存消耗: 964KB, 提交时间: 2021-02-22

package main

func EntryNodeOfLoop(pHead *ListNode) *ListNode{
    if pHead==nil {return pHead}
    slow,fast :=pHead,pHead
    for fast !=nil && fast.Next!=nil{
        fast = fast.Next.Next
        slow = slow.Next
        if fast == slow { break}
    }
    if fast ==nil || fast.Next==nil {return nil}
    slow =pHead
    for slow!=fast{
        slow=slow.Next
        fast=fast.Next
    }
    return fast 
}

上一题