141.环形链表

 首先要知道链表是怎么定义的:

第一种:

//定义一个结构体来表示一个链表中的一个节点
type ListNode struct {
    Val  int
    Next *ListNode
}
//其中,Val是一个整数,用于存储节点的值;Next是一个指向下一个节点的指针。
//使用Next指针,可以将不同的节点链接在一起,形成一个链表。
node1 := &ListNode{Val: 1}
node2 := &ListNode{Val: 2}
node3 := &ListNode{Val: 3}

node1.Next = node2
node2.Next = node3

第二种:

如果要定义多个链表,可以使用有意义的变量名来区分不同的链表

package main

import "fmt"

type ListNode struct {
    Val  int
    Next *ListNode
}

func main() {
    // 定义两个链表
    var listA, listB *ListNode

    // 操作链表 A
    listA = &ListNode{Val: 1}
    listA.Next = &ListNode{Val: 2}
    listA.Next.Next = &ListNode{Val: 3}

    // 操作链表 B
    listB = &ListNode{Val: 4}
    listB.Next = &ListNode{Val: 5}
    listB.Next.Next.Next = &ListNode{Val: 7}

    // 打印链表 A
    cur := listA
    for cur != nil {
        fmt.Printf("%d -> ", cur.Val)
        cur = cur.Next
    }
    fmt.Println("nil")

    // 打印链表 B
    cur = listB
    for cur != nil {
        fmt.Printf("%d -> ", cur.Val)
        cur = cur.Next
    }
    fmt.Println("nil")
}

法一:哈希表

同一个map数组存储遍历过的结点,这个map数组只需要指向结点的指针的键即可,不需要关心结点的值是多少,也就是map对应的key的value值。所以value可以用一个空结构体代替。

遍历链表的条件:指针指向的结点不为空时head!=nil

用if _, ok:=m[head];ok{}语句来判断head指针指向的结点是否出现在m[head]里面,ok是一个bool类型的变量,如果存在,m[head]给ok返回一个非0的值,在这里返回的是一个空结构体struct,此时ok的值为true;如果不存在,m[head]给ok返回一个0值。

如果不存在,就把节点存到/标记到map数组里,m[head]=struct{}{}。只用标记键head就可以,不需要value值存入map数组,value同一个空结构体来代替,struct{}{}只是一种特殊的数据类型,并不占据内存空间。

然后指针移到下一节点

如果跳出for循环,则返回false。

func hasCycle(head *ListNode) bool {
	m:=map[*ListNode]struct{}{}
	for head!=nil{
		if _,exists:=m[head];exists{
			return true
		}
		m[head]=struct{}{}
		head=head.Next
	}
	return false
}

时间复杂度:O(n),n为节点数

空间复杂度:O(n),n为节点数 

法二:

slow指针一步一步走;

fast指针两步两步走;

如果存在环,fast一定会和slow相遇

//快慢指针
func hasCycle2(head *ListNode) bool{
	if head==nil||head.Next==nil{
		return false
	}
	slow,fast:=head,head.Next
	for slow!=fast{
		//这里的if语句是错的
		//if slow==nil||fast==nil{
		//	return false
		//}
		//这里的代码中,每次更新慢指针和快指针时,都是将它们都更新为头结点的下一个节点,这是错误的。
		//slow=head.Next
		//fast=head.Next.Next
		//fast指针走比slow的快,所以当fast为nil或者fast.Next为nil时,就已经能说明没有环。
		if fast==nil||fast.Next==nil{
			return false
		}
		slow=slow.Next
		fast=fast.Next.Next
	}
	return true
}

时间复杂度:O(n),n为节点数

空间复杂度:O(1)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值