人间算法题:到底是不是一个环?

很多人都说人生就是一个循环,每天重复重复。

而所谓环,对于写代码的小伙伴来说是有特殊定义的。我的理解就是节点循环,就成了环。

刚好刷到一个掘金好友分享的腾讯一面算法题:判断一个单链表是不是一个环。

其实有很多办法来实现,但是我更喜欢用快慢指针来判断环的形成。思路如下:

  1. 定义一个slow指针,指向单链表的头部节点head。定义一个fast指针,初始化为head.next。
    2.然后先判断fast和fast.next是否是空,如果为空,肯定不是环。
    3.然后开始移动快慢两个指针。slow指针每次只移动一个节点,fast指针每次移动2个节点。
    4.如果在移动的过程中slow指向的节点等于fast指向的节点,那么说明循环了,这是一个环。
    5.如果移动到链表最后(假设不是环,有尾部)还是没有slow和fast节点重合,那么说明不是环。

所谓环,那么就一定会快慢指针一定会相遇。

那么用golang实现一下:

复制代码
package main

import (
    "fmt"
)

type ListNode struct {
   Val int
   Next *ListNode
}
func HasCircle(head *ListNode) bool {
    slow, fast := head, head.Next

    if fast == nil || fast.Next == nil {
        return false
    }

    for fast != nil && fast.Next != nil {
        if slow == fast {
            return true
        }

        slow = slow.Next
        fast = fast.Next.Next
    }

    return false
}

func main() {
    // create the list
    head := &ListNode{Val: 1}
    head.Next = &ListNode{Val: 2}
    head.Next.Next = &ListNode{Val: 3}
    head.Next.Next.Next = &ListNode{Val: 4}
    head.Next.Next.Next = head.Next
    fmt.Println("Is circle? ", HasCircle(head))
}

死去的记忆又在攻击我了,我想起多年前去一家互联网医疗公司面试的时候也遇到这道题,我也给出了这个解法,但是面试官一脸懵逼,无法理解我的思路。今天我仔细想想,也许是他想看到我用深度优先搜索(DFS)来实现。

所谓深度优先,就是一种递归算法,用于搜索图或树数据结构的所有顶点。该算法从起始节点开始,尽可能沿着每条路径探索,直到无法再前进为止,然后进行回溯。DFS通常使用堆栈来跟踪已发现的节点,以便进行回溯。这种算法的时间复杂度为O(V+E),其中V是顶点数,E是边数。在实际应用中,DFS还有许多应用,包括寻找连通分量、检测图中的环、拓扑排序等。

检测环,用它就对啦,实现如下所示:

···

func dfs(node *ListNode, visited map* ListNodebool) bool {

if node == nil {

return false

}

复制代码
if visited[node] {
    return true
}

visited[node] = true

return dfs(node.Next, visited)

}

func HasCircleByDFS(head *ListNode) bool {
visited := make(map* ListNodebool)

return dfs(head, visited)

}

func main() {

// create the list

head := &ListNode{Val: 1}

head.Next = &ListNode{Val: 2}

head.Next.Next = &ListNode{Val: 3}

head.Next.Next.Next = &ListNode{Val: 4}

head.Next.Next.Next = head.Next

fmt.Println("Is circle? ", HasCircleByDFS(head))

}

···

总结

有时候面试者需要去推测出题人的意图,条条道路虽然通罗马,但你的解法不一定能打动考官。

相关推荐
平头哥AI10 小时前
Day 01 | go run 跑通第一个 Go 程序,go build 留下一个能拷走的 exe
开发语言·后端·golang
2601_9622965111 小时前
如何使用Golang包路径_管理本地和远程模块引用
golang·数据转换·变量定义·常用库·编程语言区别
FfHUCisI16 小时前
GMP 调度器:Go 并发的心脏是如何跳动的
开发语言·golang·php
我不会起名字32217 小时前
一天一道算法题(26):栈的简单应用
java·数据结构·python·算法·leetcode·golang·
gsls20080817 小时前
告别 Vault 的复杂度:用 Go 标准库给 Windows 凭据管理器装上 MCP
windows·golang·mcp
名字还没想好☜18 小时前
Go 时间格式化为什么用 2006-01-02:time.Format/Parse 的参考时间、时区与解析踩坑
开发语言·后端·golang·go
FfHUCisI1 天前
Golang Map 哈希表实现
golang·哈希算法·散列表
源代码•宸1 天前
前置准备:定时微服务背景和现状
开发语言·经验分享·后端·微服务·云原生·架构·golang
李燚1 天前
把规则搬回家:三个 BC 的贫血→充血重构实录(第103篇)
golang·agent·ddd·领域驱动设计·eino·deepflux·eino adk
astronautyi2 天前
Go 运行时内存分配与 GC 位图深度剖析
开发语言·后端·golang