基础
刷题
- 多余的边
109 多余的边 II (非常难)
这道题目有三种情况,
第一类情况是节点入度为2的情况,即两个节点都指向同一个节点,一定不是有向树,且这两个中一定有一个是多余的边。
再分析这两个边,一般是最后一个边是多余的边
还有一种情况是只能删除特定的边(这里可以利用并查集找到导致成环的那个边)
这是第一类情况的两种情况
还有一类情况,入度都是1(一定有环,这里直接使用并查集)
总结
并查集
并查集只能使用于无向图,检测是否连通,是否成环。不能用于有向图
golang指针
var 定义的变量是零值。var f *Father 定义的是指针类型的零值,即 nil指针(空指针)
| 声明方式 | 初始值 | 调用Init时的处理 | 安全性 |
|---|---|---|---|
var f Father | 空切片nil | Go自动获取&f,Init内部修改f本身 | ✅ 安全 |
var f *Father | 空指针nil | 直接使用nil指针,Init内部尝试解引用nil | ❌ 运行时错误 |
Go 的方法调用自动转换机制
Go 语言规范规定了方法调用的自动转换规则:
- 当你用值类型变量调用指针接收器方法时,Go 会自动将值转换为指针(即自动取地址
&f) - 当你用指针类型变量调用值接收器方法时,Go 会自动将指针解引用为值(即自动解引用
*p)
nil 指针与其他 nil 类型的区别
注意区分 nil 指针与其他 nil 类型(它们的行为不同):
| 类型 | nil 状态 | 安全操作 | 危险操作 |
|---|---|---|---|
指针(*int) | nil | 比较 p == nil | 解引用 *p |
切片([]int) | nil | len(p)、cap(p)、append(p, 1) | 索引访问 p[0] |
映射(map[int]int) | nil | 比较 m == nil | 写入 m[1] = 2 |
接口(interface{}) | nil | 比较 i == nil | 类型断言 i.(int) |
当你尝试解引用 nil 指针(访问它指向的内存)时,Go 程序会立即崩溃:
var p *int
*p = 10 // 运行时 panic: runtime error: invalid memory address or nil pointer dereference
- 这是 Go 的内存安全机制:防止程序访问无效内存
- 崩溃会导致程序终止,无法继续执行后续代码