文章目录

  • 547. 省份数量
    • 描述
    • 示例 1
    • 示例 2
    • 提示
    • 解题思路
      • 核心分析
      • 问题转化
      • 算法选择策略
        • 1. 深度优先搜索 (DFS)
        • 2. 广度优先搜索 (BFS)
        • 3. 并查集 (Union-Find)
      • 算法实现详解
        • 方法一:深度优先搜索 (DFS)
        • 方法二:广度优先搜索 (BFS)
        • 方法三:并查集 (Union-Find)
      • 算法选择
        • 1. 深度优先搜索 (DFS)
        • 2. 广度优先搜索 (BFS)
        • 3. 并查集 (Union-Find)
      • 数学证明
        • 并查集正确性证明
        • 时间复杂度分析
      • 执行流程图
      • 算法可视化
      • 实际应用
      • 算法优化技巧
        • 1. 内存优化
        • 2. 早期终止
        • 3. 对称性利用
      • 扩展思考
      • 相关问题
      • 测试用例设计
      • 性能对比
      • 常见错误
      • 总结
      • 算法流程图
      • 详细解题步骤
        • 方法一:深度优先搜索 (DFS)
        • 方法二:广度优先搜索 (BFS)
        • 方法三:并查集 (Union-Find)
      • 复杂度分析
      • 边界情况处理
      • 优化技巧
    • 完整题解代码

547. 省份数量

描述

有 n 个城市,其中一些彼此相连,另一些没有相连。如果城市 a 与城市 b 直接相连,且城市 b 与城市 c 直接相连,那么城市 a 与城市 c 间接相连。

省份 是一组直接或间接相连的城市,组内不含其他没有相连的城市。

给你一个 n x n 的矩阵 isConnected ,其中 isConnected[i][j] = 1 表示第 i 个城市和第 j 个城市直接相连,而 isConnected[i][j] = 0 表示二者不直接相连。

返回矩阵中 省份 的数量。

示例 1

在这里插入图片描述

输入:isConnected = [[1,1,0],[1,1,0],[0,0,1]]
输出:2

示例 2

在这里插入图片描述

输入:isConnected = [[1,0,0],[0,1,0],[0,0,1]]
输出:3

提示

  • 1 <= n <= 200
  • n == isConnected.length
  • n == isConnected[i].length
  • isConnected[i][j] 为 1 或 0
  • isConnected[i][i] == 1
  • isConnected[i][j] == isConnected[j][i]

解题思路

核心分析

这道题是一个经典的图论连通性问题。核心思想是计算无向图中连通分量的数量。

问题本质:给定一个无向图的邻接矩阵,计算图中连通分量的个数。

关键洞察

  • 每个城市是一个节点,城市间的连接关系构成边
  • 省份就是连通分量,即相互可达的节点集合
  • 可以通过遍历算法(DFS/BFS)或并查集来求解

问题转化

原始问题:计算n个城市中省份的数量

图论转化

  1. 将城市抽象为图中的节点
  2. 将城市间的连接关系抽象为图中的边
  3. 省份数量 = 连通分量数量

数学建模

  • 节点集合:V = {0, 1, 2, …, n-1}
  • 边集合:E = {(i, j) | isConnected[i][j] = 1}
  • 目标:计算图G(V, E)中连通分量的数量

算法选择策略

1. 深度优先搜索 (DFS)
  • 适用场景:连通性问题,需要遍历所有可达节点
  • 优势:实现简单,递归清晰,空间效率高
  • 劣势:可能栈溢出,不适合极大数据量
2. 广度优先搜索 (BFS)
  • 适用场景:连通性问题,需要层次遍历
  • 优势:避免栈溢出,适合大数据量
  • 劣势:需要队列空间,实现稍复杂
3. 并查集 (Union-Find)
  • 适用场景:动态连通性问题,需要频繁合并操作
  • 优势:支持动态操作,理论复杂度最优
  • 劣势:实现复杂,常数项较大

算法实现详解

方法一:深度优先搜索 (DFS)

核心思想:从每个未访问的节点开始,递归访问所有可达节点

算法步骤

  1. 初始化访问数组visited,记录每个节点是否被访问
  2. 遍历所有节点,对每个未访问的节点:
    • 调用DFS函数访问该节点及其所有可达节点
    • 连通分量数量加1
  3. DFS函数实现:
    • 标记当前节点为已访问
    • 遍历所有与当前节点相连的节点
    • 对每个未访问的相连节点递归调用DFS

代码实现

func findCircleNumDFS(isConnected [][]int) int {n := len(isConnected)if n == 0 {return 0}visited := make([]bool, n)count := 0for i := 0; i < n; i++ {if !visited[i] {dfs(isConnected, visited, i)count++}}return count
}func dfs(isConnected [][]int, visited []bool, city int) {visited[city] = truefor nextCity := 0; nextCity < len(isConnected); nextCity++ {if isConnected[city][nextCity] == 1 && !visited[nextCity] {dfs(isConnected, visited, nextCity)}}
}

时间复杂度分析

  • 每个节点最多被访问一次:O(n)
  • 每次访问需要遍历所有相邻节点:O(n)
  • 总时间复杂度:O(n²)

空间复杂度分析

  • 访问数组:O(n)
  • 递归调用栈深度:O(n)
  • 总空间复杂度:O(n)
方法二:广度优先搜索 (BFS)

核心思想:使用队列进行层次遍历,访问所有可达节点

算法步骤

  1. 初始化访问数组和队列
  2. 遍历所有节点,对每个未访问的节点:
    • 将节点加入队列
    • 标记为已访问
    • 连通分量数量加1
    • 执行BFS遍历
  3. BFS函数实现:
    • 从队列中取出节点
    • 遍历所有与当前节点相连的节点
    • 将未访问的相连节点加入队列并标记为已访问

代码实现

func findCircleNumBFS(isConnected [][]int) int {n := len(isConnected)if n == 0 {return 0}visited := make([]bool, n)count := 0for i := 0; i < n; i++ {if !visited[i] {bfs(isConnected, visited, i)count++}}return count
}func bfs(isConnected [][]int, visited []bool, startCity int) {queue := []int{startCity}visited[startCity] = truefor len(queue) > 0 {city := queue[0]queue = queue[1:]for nextCity := 0; nextCity < len(isConnected); nextCity++ {if isConnected[city][nextCity] == 1 && !visited[nextCity] {visited[nextCity] = truequeue = append(queue, nextCity)}}}
}

时间复杂度:O(n²)
空间复杂度:O(n)

方法三:并查集 (Union-Find)

核心思想:使用并查集维护连通性,通过合并操作统计连通分量

算法步骤

  1. 初始化并查集,每个节点自成一个集合
  2. 遍历邻接矩阵,对每个连接关系:
    • 合并相连的两个节点到同一集合
  3. 统计最终集合的数量

并查集优化

  • 路径压缩:在查找时压缩路径,减少后续查找时间
  • 按秩合并:将较小的树合并到较大的树上,保持树的平衡

代码实现

type UnionFind struct {parent []intrank   []intcount  int
}func NewUnionFind(n int) *UnionFind {parent := make([]int, n)rank := make([]int, n)for i := 0; i < n; i++ {parent[i] = irank[i] = 1}return &UnionFind{parent: parent,rank:   rank,count:  n,}
}func (uf *UnionFind) Find(x int) int {if uf.parent[x] != x {uf.parent[x] = uf.Find(uf.parent[x]) // 路径压缩}return uf.parent[x]
}func (uf *UnionFind) Union(x, y int) {rootX := uf.Find(x)rootY := uf.Find(y)if rootX == rootY {return}// 按秩合并if uf.rank[rootX] < uf.rank[rootY] {uf.parent[rootX] = rootY} else if uf.rank[rootX] > uf.rank[rootY] {uf.parent[rootY] = rootX} else {uf.parent[rootY] = rootXuf.rank[rootX]++}uf.count--
}func (uf *UnionFind) Count() int {return uf.count
}

时间复杂度:O(n² × α(n)),其中α(n)是阿克曼函数的反函数
空间复杂度:O(n)

算法选择

1. 深度优先搜索 (DFS)
  • 时间复杂度:O(n²),其中 n 是城市数量
  • 空间复杂度:O(n),递归调用栈的深度
  • 适用场景:适合处理连通性问题
2. 广度优先搜索 (BFS)
  • 时间复杂度:O(n²)
  • 空间复杂度:O(n),队列的空间
  • 适用场景:适合处理连通性问题,避免递归栈溢出
3. 并查集 (Union-Find)
  • 时间复杂度:O(n² × α(n)),其中 α(n) 是阿克曼函数的反函数
  • 空间复杂度:O(n)
  • 适用场景:适合处理动态连通性问题

数学证明

并查集正确性证明

定理:并查集算法能正确计算连通分量的数量。

证明

  1. 初始化正确性

    • 初始时每个节点自成一个集合
    • 集合数量等于节点数量
  2. 合并操作正确性

    • 每次合并操作将两个连通分量合并为一个
    • 集合数量减少1
  3. 最终结果正确性

    • 所有相连的节点都在同一集合中
    • 不同连通分量的节点在不同集合中
    • 集合数量等于连通分量数量
时间复杂度分析

定理:并查集算法的时间复杂度为O(n² × α(n))。

证明

  • 每个节点最多参与n次合并操作
  • 每次合并操作的时间复杂度为O(α(n))
  • 总时间复杂度为O(n² × α(n))

执行流程图

开始: 输入邻接矩阵
选择算法
DFS算法
BFS算法
并查集算法
初始化访问数组
遍历所有节点
节点是否已访问?
调用DFS函数
继续下一个节点
连通分量数量+1
是否遍历完成?
返回结果
初始化访问数组和队列
遍历所有节点
节点是否已访问?
调用BFS函数
继续下一个节点
连通分量数量+1
是否遍历完成?
初始化并查集
遍历邻接矩阵
是否存在连接?
合并两个节点
继续下一个元素
是否遍历完成?
返回集合数量
结束

算法可视化

DFS遍历过程
图结构
邻接矩阵
访问城市0
访问城市1
连通分量1完成
访问城市2
连通分量2完成
城市1
城市0
城市2
1 1 0
1 1 0
0 0 1

实际应用

  1. 社交网络分析:计算朋友圈的数量
  2. 网络拓扑分析:计算网络中的连通区域
  3. 地理信息系统:计算地理区域的连通性
  4. 电路设计:分析电路的连通性
  5. 生物信息学:分析蛋白质相互作用网络

算法优化技巧

1. 内存优化
// 使用位运算优化访问数组
visited := make([]uint64, (n+63)/64)
2. 早期终止
// 如果所有节点都已访问,可以提前终止
if count == n {return 1
}
3. 对称性利用
// 利用邻接矩阵的对称性,只遍历上三角
for i := 0; i < n; i++ {for j := i + 1; j < n; j++ {if isConnected[i][j] == 1 {// 处理连接关系}}
}

扩展思考

  1. 有向图:如果是有向图,如何计算强连通分量?
  2. 加权图:如果边有权重,如何定义连通性?
  3. 动态图:如果图结构动态变化,如何维护连通性?
  4. 大规模图:对于超大规模图,如何优化算法?
  5. 并行算法:如何设计并行版本的连通分量算法?

相关问题

  1. 200. 岛屿数量:二维网格中的连通分量问题
  2. 130. 被围绕的区域:连通分量的边界处理
  3. 399. 除法求值:带权图的连通性问题
  4. 684. 冗余连接:并查集在最小生成树中的应用
  5. 685. 冗余连接 II:有向图的连通性问题

测试用例设计

// 基础测试用例
isConnected1 := [][]int{{1, 1, 0},{1, 1, 0},{0, 0, 1},
}
expected1 := 2isConnected2 := [][]int{{1, 0, 0},{0, 1, 0},{0, 0, 1},
}
expected2 := 3// 边界测试
isConnected3 := [][]int{{1}}
expected3 := 1var isConnected4 [][]int
expected4 := 0// 极值测试
isConnected5 := [][]int{{1, 1, 1},{1, 1, 1},{1, 1, 1},
}
expected5 := 1// 复杂情况
isConnected6 := [][]int{{1, 0, 0, 1},{0, 1, 1, 0},{0, 1, 1, 1},{1, 0, 1, 1},
}
expected6 := 1

性能对比

算法时间复杂度空间复杂度常数项适用场景
DFSO(n²)O(n)一般情况
BFSO(n²)O(n)中等大数据量
并查集O(n² × α(n))O(n)动态连通性

常见错误

  1. 访问标记错误:忘记标记节点为已访问
  2. 递归终止错误:递归函数没有正确的终止条件
  3. 数组越界:访问邻接矩阵时越界
  4. 并查集初始化错误:parent数组初始化不正确
  5. 边界处理错误:没有正确处理空矩阵或单个节点

总结

省份数量 是一道经典的图论连通性问题,核心在于理解连通分量的概念和计算算法。

最优解法DFS或BFS算法,具有以下优势:

  1. 时间复杂度合理:O(n²)
  2. 实现简单:递归或队列遍历
  3. 空间效率高:只需要O(n)额外空间
  4. 应用广泛:是图遍历的经典模板题

这道题体现了图论算法中的重要思想:

  • 连通性分析:通过遍历确定节点间的可达性
  • 访问标记:避免重复访问,提高算法效率
  • 问题建模:将实际问题抽象为图论问题

并查集算法虽然理论复杂度最优,但在实际应用中,由于常数项较大,对于中等规模的问题,DFS/BFS算法往往更实用。

算法流程图

开始
初始化访问数组 visited
遍历所有城市 i
城市 i 是否已访问?
DFS/BFS 遍历连通分量
继续下一个城市
省份数量 + 1
是否遍历完所有城市?
返回省份数量
结束
标记当前城市为已访问
遍历所有相邻城市
相邻城市是否已访问?
递归访问相邻城市
继续下一个相邻城市
是否遍历完所有相邻城市?
返回

详细解题步骤

方法一:深度优先搜索 (DFS)
  1. 初始化:创建访问数组 visited,记录每个城市是否被访问过
  2. 遍历城市:从每个未访问的城市开始进行DFS
  3. DFS过程
    • 标记当前城市为已访问
    • 遍历所有与当前城市相连的城市
    • 对每个未访问的相连城市递归调用DFS
  4. 计数:每次开始新的DFS时,省份数量加1
方法二:广度优先搜索 (BFS)
  1. 初始化:创建访问数组和队列
  2. 遍历城市:从每个未访问的城市开始进行BFS
  3. BFS过程
    • 将当前城市加入队列
    • 标记为已访问
    • 从队列中取出城市,遍历其所有相连城市
    • 将未访问的相连城市加入队列
  4. 计数:每次开始新的BFS时,省份数量加1
方法三:并查集 (Union-Find)
  1. 初始化:创建并查集,每个城市自成一个集合
  2. 合并操作:遍历邻接矩阵,将相连的城市合并到同一集合
  3. 统计集合:统计最终有多少个不同的集合

复杂度分析

方法时间复杂度空间复杂度优势劣势
DFSO(n²)O(n)实现简单,递归清晰可能栈溢出
BFSO(n²)O(n)避免栈溢出需要队列
并查集O(n² × α(n))O(n)适合动态连通性实现复杂

边界情况处理

  1. 空矩阵:返回0
  2. 单个城市:返回1
  3. 所有城市都不相连:返回n
  4. 所有城市都相连:返回1

优化技巧

  1. 提前返回:如果所有城市都已访问,可以提前结束
  2. 对称性利用:由于是无向图,邻接矩阵是对称的
  3. 内存优化:使用位运算优化访问数组的存储

完整题解代码

package mainimport ("fmt"
)// 方法一:深度优先搜索 (DFS)
// 时间复杂度:O(n²),空间复杂度:O(n)
func findCircleNumDFS(isConnected [][]int) int {n := len(isConnected)if n == 0 {return 0}// 访问数组,记录每个城市是否被访问过visited := make([]bool, n)count := 0// 从每个未访问的城市开始DFSfor i := 0; i < n; i++ {if !visited[i] {dfs(isConnected, visited, i)count++}}return count
}// DFS辅助函数
func dfs(isConnected [][]int, visited []bool, city int) {visited[city] = true// 遍历所有与当前城市相连的城市for nextCity := 0; nextCity < len(isConnected); nextCity++ {if isConnected[city][nextCity] == 1 && !visited[nextCity] {dfs(isConnected, visited, nextCity)}}
}// 方法二:广度优先搜索 (BFS)
// 时间复杂度:O(n²),空间复杂度:O(n)
func findCircleNumBFS(isConnected [][]int) int {n := len(isConnected)if n == 0 {return 0}visited := make([]bool, n)count := 0// 从每个未访问的城市开始BFSfor i := 0; i < n; i++ {if !visited[i] {bfs(isConnected, visited, i)count++}}return count
}// BFS辅助函数
func bfs(isConnected [][]int, visited []bool, startCity int) {queue := []int{startCity}visited[startCity] = truefor len(queue) > 0 {city := queue[0]queue = queue[1:]// 遍历所有与当前城市相连的城市for nextCity := 0; nextCity < len(isConnected); nextCity++ {if isConnected[city][nextCity] == 1 && !visited[nextCity] {visited[nextCity] = truequeue = append(queue, nextCity)}}}
}// 方法三:并查集 (Union-Find)
// 时间复杂度:O(n² × α(n)),空间复杂度:O(n)
func findCircleNumUnionFind(isConnected [][]int) int {n := len(isConnected)if n == 0 {return 0}// 初始化并查集uf := NewUnionFind(n)// 遍历邻接矩阵,合并相连的城市for i := 0; i < n; i++ {for j := i + 1; j < n; j++ { // 利用对称性,只遍历上三角if isConnected[i][j] == 1 {uf.Union(i, j)}}}return uf.Count()
}// 并查集结构
type UnionFind struct {parent []intrank   []intcount  int
}// 创建新的并查集
func NewUnionFind(n int) *UnionFind {parent := make([]int, n)rank := make([]int, n)for i := 0; i < n; i++ {parent[i] = irank[i] = 1}return &UnionFind{parent: parent,rank:   rank,count:  n,}
}// 查找根节点(路径压缩)
func (uf *UnionFind) Find(x int) int {if uf.parent[x] != x {uf.parent[x] = uf.Find(uf.parent[x]) // 路径压缩}return uf.parent[x]
}// 合并两个集合(按秩合并)
func (uf *UnionFind) Union(x, y int) {rootX := uf.Find(x)rootY := uf.Find(y)if rootX == rootY {return}// 按秩合并if uf.rank[rootX] < uf.rank[rootY] {uf.parent[rootX] = rootY} else if uf.rank[rootX] > uf.rank[rootY] {uf.parent[rootY] = rootX} else {uf.parent[rootY] = rootXuf.rank[rootX]++}uf.count--
}// 返回集合数量
func (uf *UnionFind) Count() int {return uf.count
}// 方法四:优化的DFS(使用栈避免递归)
// 时间复杂度:O(n²),空间复杂度:O(n)
func findCircleNumDFSIterative(isConnected [][]int) int {n := len(isConnected)if n == 0 {return 0}visited := make([]bool, n)count := 0for i := 0; i < n; i++ {if !visited[i] {dfsIterative(isConnected, visited, i)count++}}return count
}// 迭代式DFS
func dfsIterative(isConnected [][]int, visited []bool, startCity int) {stack := []int{startCity}visited[startCity] = truefor len(stack) > 0 {city := stack[len(stack)-1]stack = stack[:len(stack)-1]for nextCity := 0; nextCity < len(isConnected); nextCity++ {if isConnected[city][nextCity] == 1 && !visited[nextCity] {visited[nextCity] = truestack = append(stack, nextCity)}}}
}// 测试函数
func main() {// 测试用例1:示例1isConnected1 := [][]int{{1, 1, 0},{1, 1, 0},{0, 0, 1},}fmt.Println("测试用例1:")fmt.Printf("输入: %v\n", isConnected1)fmt.Printf("DFS结果: %d\n", findCircleNumDFS(isConnected1))fmt.Printf("BFS结果: %d\n", findCircleNumBFS(isConnected1))fmt.Printf("并查集结果: %d\n", findCircleNumUnionFind(isConnected1))fmt.Printf("迭代DFS结果: %d\n", findCircleNumDFSIterative(isConnected1))fmt.Println("期望结果: 2")fmt.Println()// 测试用例2:示例2isConnected2 := [][]int{{1, 0, 0},{0, 1, 0},{0, 0, 1},}fmt.Println("测试用例2:")fmt.Printf("输入: %v\n", isConnected2)fmt.Printf("DFS结果: %d\n", findCircleNumDFS(isConnected2))fmt.Printf("BFS结果: %d\n", findCircleNumBFS(isConnected2))fmt.Printf("并查集结果: %d\n", findCircleNumUnionFind(isConnected2))fmt.Printf("迭代DFS结果: %d\n", findCircleNumDFSIterative(isConnected2))fmt.Println("期望结果: 3")fmt.Println()// 测试用例3:所有城市相连isConnected3 := [][]int{{1, 1, 1},{1, 1, 1},{1, 1, 1},}fmt.Println("测试用例3 (所有城市相连):")fmt.Printf("输入: %v\n", isConnected3)fmt.Printf("DFS结果: %d\n", findCircleNumDFS(isConnected3))fmt.Printf("BFS结果: %d\n", findCircleNumBFS(isConnected3))fmt.Printf("并查集结果: %d\n", findCircleNumUnionFind(isConnected3))fmt.Printf("迭代DFS结果: %d\n", findCircleNumDFSIterative(isConnected3))fmt.Println("期望结果: 1")fmt.Println()// 测试用例4:单个城市isConnected4 := [][]int{{1}}fmt.Println("测试用例4 (单个城市):")fmt.Printf("输入: %v\n", isConnected4)fmt.Printf("DFS结果: %d\n", findCircleNumDFS(isConnected4))fmt.Printf("BFS结果: %d\n", findCircleNumBFS(isConnected4))fmt.Printf("并查集结果: %d\n", findCircleNumUnionFind(isConnected4))fmt.Printf("迭代DFS结果: %d\n", findCircleNumDFSIterative(isConnected4))fmt.Println("期望结果: 1")fmt.Println()// 测试用例5:空矩阵var isConnected5 [][]intfmt.Println("测试用例5 (空矩阵):")fmt.Printf("输入: %v\n", isConnected5)fmt.Printf("DFS结果: %d\n", findCircleNumDFS(isConnected5))fmt.Printf("BFS结果: %d\n", findCircleNumBFS(isConnected5))fmt.Printf("并查集结果: %d\n", findCircleNumUnionFind(isConnected5))fmt.Printf("迭代DFS结果: %d\n", findCircleNumDFSIterative(isConnected5))fmt.Println("期望结果: 0")fmt.Println()// 测试用例6:复杂情况isConnected6 := [][]int{{1, 0, 0, 1},{0, 1, 1, 0},{0, 1, 1, 1},{1, 0, 1, 1},}fmt.Println("测试用例6 (复杂情况):")fmt.Printf("输入: %v\n", isConnected6)fmt.Printf("DFS结果: %d\n", findCircleNumDFS(isConnected6))fmt.Printf("BFS结果: %d\n", findCircleNumBFS(isConnected6))fmt.Printf("并查集结果: %d\n", findCircleNumUnionFind(isConnected6))fmt.Printf("迭代DFS结果: %d\n", findCircleNumDFSIterative(isConnected6))fmt.Println("期望结果: 1")
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/90119.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/90119.shtml
英文地址,请注明出处:http://en.pswp.cn/web/90119.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

09_Spring Boot 整合 Freemarker 模板引擎的坑

09_Spring Boot 整合 Freemarker 模板引擎的坑 1.背景&#xff1a; springboot 版本&#xff1a;3.0.2 2. 引入依赖 在 pom.xml 中添加&#xff1a; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web<…

十七、【Linux系统yum仓库管理】替换阿里源、搭建本地yum源

替换阿里源、搭建本地yum源本章学习目标内容简介阿里外网源核心功能本地yum核心功能操作演示替换阿里外网源备份原有yum源清理冲突配置下载阿里源配置文件添加EPEL扩展源清理缓存重建索引验证源状态测试安装软件使用镜像搭建本地仓库准备ISO镜像创建挂载点目录挂载iso文件验证挂…

家庭网络怎么进行公网IP获取,及内网端口映射外网访问配置,附无公网IP提供互联网连接方案

在家庭网络中&#xff0c;我们常常需要通过公网IP来访问内网中的设备&#xff0c;比如家庭NAS、Web服务器或监控摄像头。要实现这个目标&#xff0c;首先要确保你的网络具有一个可用的公网IP&#xff0c;然后通过路由器配置端口映射&#xff08;Port Forwarding&#xff09;。如…

(LeetCode 面试经典 150 题 ) 128. 最长连续序列 (哈希表)

题目&#xff1a;128. 最长连续序列 思路&#xff1a;哈希表&#xff0c;时间复杂度0(n)。 用集合set来实现哈希表的功能&#xff0c;记录所有出现的元素。然后遍历元素&#xff0c;细节看注释。 C版本&#xff1a; class Solution { public:int longestConsecutive(vector&…

Altera Quartus:BAT批处理实现一键sof文件转换为jic文件

sof文件是Quartus编译默认生成的程序文件&#xff0c;用于通过JTAG口下载到FPGA内部RAM&#xff0c;断电程序会丢失&#xff0c;jic文件是用于固化到外部Flash中的程序文件&#xff0c;断电程序不会丢失。本文介绍如何通过批处理文件实现sof到jic的一键自动化转换。 Quartus工程…

基于单片机婴儿床/婴儿摇篮/婴儿车设计/婴儿监护系统

传送门 &#x1f449;&#x1f449;&#x1f449;&#x1f449;其他作品题目速选一览表 &#x1f449;&#x1f449;&#x1f449;&#x1f449;其他作品题目功能速览 概述 本设计实现了一种基于单片机的多功能智能婴儿监护系统&#xff0c;集成于婴儿床、摇篮或婴儿车中…

Typora + 七牛云图床终极配置教程

本文是一份超详细的 Typora 七牛云图床配置指南&#xff0c;旨在帮助你实现图片“即插即用”的顺滑写作体验。我们将一步步完成所有配置&#xff0c;并特别针对配置过程中最常见的三个错误&#xff1a;ENOTFOUND (找不到服务器)、401 (无权访问) 和 Document not found (文件不…

高性能熔断限流实现:Spring Cloud Gateway 在电商系统的实战优化

一、为什么需要高性能熔断限流&#xff1f; 在电商系统中&#xff0c;尤其是大促期间&#xff0c;系统面临的流量可能是平时的数十倍甚至上百倍。 这样的场景下&#xff0c;熔断限流不再是可选功能&#xff0c;而是保障系统稳定的生命线。传统方案的问题&#xff1a; 限流精度不…

计算机网络1.1:计算机网络在信息时代的作用

计算机网络已由一种通信基础设施发展成为一种重要的信息服务基础设施。计算机网络已经像水、电、煤气这些基础设施一样&#xff0c;成为我们生活中不可或缺的一部分。

Component cannot be used as a JSX component

今天在使用 React Ts&#xff0c;使用 react-icons 这个库的时候&#xff0c;遇到了这个问题&#xff1a;原因用一句话概括就是 Ts 的版本太低了&#xff01; 我的 package.json&#xff1a; {"name": "frontend","version": "0.1.0"…

Centos安装最新docker以及ubuntu安装docker

Centos安装最新版本docker1.更新阿里源,更新之前先做备份mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup更新阿里源wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo2.运行 yum makecache 生成缓存…

网络基础15-16:MSTP +VRRP综合实验

MSTP 、VRRP综合实验&#xff0c;MSTP涵盖根桥选举、边缘端口、BPDU 保护、根保护、TC 保护 等功能验证。一、实验拓扑与设备规划核心层&#xff1a;LSW1&#xff08;VLAN10 根桥、VLAN20 备份根&#xff09;、LSW2&#xff08;VLAN20 根桥、VLAN10 备份根&#xff09;。接入层…

nvm安装详细教程、镜像、环境变量(安装node.js,npm,nvm)

一、什么是nodejs、nvm、npm 1、node.js 角色&#xff1a;JavaScript 的运行时环境&#xff08;runtime&#xff09;。 作用&#xff1a;让 JavaScript 脱离浏览器&#xff0c;直接在服务器或本地运行&#xff08;比如用 node app.js 执行代码&#xff09;。 包含&#xff1…

【JS】获取元素宽高(例如div)

文章目录基础用法基础用法 高度类型选择&#xff08;宽度同理&#xff09;&#xff1a; 属性描述offsetHeight包含边框内边距内容clientHeight包含内边距内容&#xff08;不包含边框&#xff09;scrollHeight包含滚动内容的全高&#xff08;含隐藏部分&#xff09; JS可使用g…

Kubernetes(k8s)中命令行查看Pod所属控制器之方法总结

在Kubernetes中&#xff0c;可以通过以下方法查看Pod所属的控制器&#xff1a;方法1&#xff1a;使用 kubectl describe pod命令kubectl describe pod <pod name>Events:Type Reason Age From Message---- ------ ---- ---- …

Zabbix 企业级高级应用

目录 一、Zabbix 监控基础与核心价值 二、网络自动发现&#xff1a;批量主机自动化管理 &#xff08;一&#xff09;网络自动发现的核心能力与局限 &#xff08;二&#xff09;网络自动发现完整流程 &#xff08;三&#xff09;网络自动发现配置步骤 1. 客户端&#xff0…

行业分类表sql

1.创建行业表行业信息表(hy_industries)名类型长度小数点Not Null虚拟键默认值注释industries_idintTRUEFALSETRUE行业IDindustry_codevarchar5FALSEFALSEFALSE行业编码industry_namevarchar100FALSEFALSEFALSE行业名称parent_idvarchar50FALSEFALSEFALSE父级行业ID(顶级为NULL…

PPIO × Lemon AI:一键解锁全流程自动化开发能力

传统开发需手动编写代码、调试及测试&#xff0c;耗时且依赖技术能力。AI Agent 可以帮助开发者进行高效开发&#xff0c;从需求理解到代码生成、测试、部署一站式完成。Lemon AI是一款开源的通用智能体&#xff0c;能够实现从需求计划到成果交付全流程自动化。它可以在虚拟环境…

基于单片机无线防丢/儿童防丢报警器

传送门 &#x1f449;&#x1f449;&#x1f449;&#x1f449;其他作品题目速选一览表 &#x1f449;&#x1f449;&#x1f449;&#x1f449;其他作品题目功能速览 概述 本设计实现了一种基于单片机的无线防丢报警系统&#xff0c;主要用于防止贵重物品&#xff08;如…

50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | NotesApp(便签笔记组件)

&#x1f4c5; 我们继续 50 个小项目挑战&#xff01;—— NotesApp组件 仓库地址&#xff1a;https://github.com/SunACong/50-vue-projects 项目预览地址&#xff1a;https://50-vue-projects.vercel.app/。 使用 Vue 3 的 Composition API 搭配 TailwindCSS 和 marked 库&…