go 链表中环的监测

注:详细代码到https://github.com/go-snail/arithmetic/tree/master/link下载。

链表中环的监测

1、判断是否存在环

通过快慢指针方式。slow和fast,初始化slow=fast=head,循环执行以下操作slow = slow.next,fast = fast.next.next,判断slow == fast,若slow == fast,记交点为p,则存在环,否则不存在。

2、求取环的长度

从p开始执行以下操作slow=slow.next,fast=fast.next,再次相交时,执行的操作数,即为环的长度。

3、找出环的连接点

go 链表中环的监测_第1张图片

如果单链表有环,按照方法二的思路,走得快的指针fast若与走的慢的指针slow相遇时,slow指针肯定没有遍历完链表,而fast指针已经在环内循环了n圈(n>=1)。假设slow指针走了s步,则fast指针走了2s步(fast步数还等于s加上在环上多转的n圈),设环厂为r,则满足如下关系表达式:

2s = s + nr 推导出s=nr

设整个链表长为L,入口环与相遇点b距离为b,起点到环入口点的距离为a。则满足如下关系表达式:

r = L-a

a+b = s = nr = (n-1)*r+r = (n-1)*r+L-a 推导出a = (n-1)r+(L-a-b)

如上面的图可得知,L-a-b为相遇点b到环入口点的距离,从链表头到环入口点a的距离a等于n-1循环内环+相遇点到环入口点的距离。于是从链表头与相遇点分别设一个指针,每次各走一步,两个指针必定相遇,且相遇第一点为环的入口点。

编码如下:

type chainNodestruct {

    num    int

    next *chainNode

}

var gc =make(map[*chainNode]int, 0)

func NewChainNode() *chainNode {

    return &chainNode{0, nil}

}

func (l *chainNode)ListChain() {

    for l.next != nil && gc[l.next] ==0 {

    gc[l.next] =1

     fmt.Printf(" %d", l.next.num)

    l = l.next

    }

}

func (pHead *chainNode)CreateChain() {

var temp *chainNode

var a *chainNode

for i :=1; i <=7; i++ {

temp = NewChainNode()

temp.num = i

pHead.next = temp

pHead = pHead.next

if i ==4 {

a = temp

}

}

temp.next = a

}

func (pHead *chainNode)Checkloop()  {

var fast =  pHead.next

var slow = pHead.next

slow = slow.next

fast = fast.next.next

for slow != fast && fast != nil && slow != nil {

fast = fast.next.next

slow = slow.next

}

fmt.Println("交点b:", fast.num)

slow = slow.next

len1 :=1

  //fast不动,slow继续走再次相等则为环的长度

  for slow != fast {

slow = slow.next

len1++

}

fmt.Println("This length of cycle is:", len1)

//求长度

  len2 :=0

  slow = pHead.next

for slow != fast {

fast = fast.next

slow = slow.next

len2 ++

}

fmt.Println("This length of chain is:", len1 + len2)

}

你可能感兴趣的:(go 链表中环的监测)