算法之旅:LeetCode 拓扑排序由简入繁完全攻略

前言

欢迎来到我的算法探索博客,在这里,我将通过解析精选的LeetCode题目,与您分享深刻的解题思路、多元化的解决方案以及宝贵的实战经验,旨在帮助每一位读者提升编程技能,领略算法之美。
👉更多高频有趣LeetCode算法题

拓扑排序是一种适用于 有向无环图(DAG) 的重要算法,常用于解决依赖关系问题,如课程安排、任务调度等。在本文中,我们将通过以下四道题目,详细讲解拓扑排序的原理、实现方式及其多样化应用场景:

1557. 可以到达所有点的最少点数目207. 课程表
210. 课程表 II802. 找到最终的安全状态

在这里插入图片描述

拓扑排序基础知识

核心思想:

拓扑排序旨在为图中的节点安排一种线性顺序,使得对每条有向边 (u, v),节点 u 总是排在 v 之前。

本节我们利用 入度表 + 广度优先搜索(BFS) 实现拓扑排序:

  1. 入度的概念
  • 每个节点的 入度 是指有多少条边指向这个节点。
  • 如果某个节点的入度为 0,说明它没有依赖,可以作为起点开始。
  1. 拓扑排序的原理
  • 将所有入度为 0 的节点加入队列(表示这些节点可以直接开始,不需要经过任何依赖)。
  • 从队列中逐一取出节点,将其所有出边的目标节点的入度减 1 (被引用次数-1)
  • 如果某个节点的入度变为 0,将其加入队列。
  • 重复这一过程,直到队列为空。
  • 如果完成所有节点的拓扑排序,说明图中无环;否则,说明存在环。

适用条件:

图必须是 有向无环图(DAG)
若存在环,则无法构建拓扑排序。

常见实现方法:

  • Kahn算法: 基于入度统计。逐步移除入度为 0 的节点,动态更新图结构。
  • DFS(深度优先搜索): 通过后序遍历逆序输出结果。

实战:经典例题讲解

1557. 可以到达所有点的最少点数目

🪸题目描述

在这里插入图片描述

🪷核心思路

这是一个经典的入度问题,这题可以看作是 拓扑排序思想的局部应用,利用入度信息快速判断需要作为起点的节点。初具雏形。
若一个节点的入度为 0,则必须从它出发才能到达该节点。
因此,我们只需要找出所有入度为 0 的节点即可。

  1. 构建入度数组
for(List<Integer> a : edges){
    inDegree[a.get(1)]++;
}
  • 遍历所有边,计算每个节点的入度 (即有多少条边指向该节点,被引用的次数)
  • 结果存储在 inDegree 数组中,其中 inDegree[i] 表示节点 i 的入度。
  1. 找出入度为 0 的节点
for (int i = 0; i < n; i++) {
    if (inDegree[i] == 0) {
        res.add(i);
    }
}
  • 遍历所有节点,检查哪些节点的入度为 0
  • 入度为 0 的节点没有任何依赖,它们必须作为路径的起点,加入结果列表 res。
  1. 返回结果
    最终返回 res,即所有入度为 0 的节点构成的集合。

🌿代码实现

Java
class Solution {
    public List<Integer> findSmallestSetOfVertices(int n, List<List<Integer>> edges) {
        List<Integer> res = new ArrayList<>();
        int[] inDegree = new int[n];

        // 构建入度数组
        // 其中每个元素表示对应被依赖的次数,也就是 入度
        for(List<Integer> a : edges){
            inDegree[a.get(1)]++;
        }

        // 将所有入度为 0 的课程加入队列
        Queue<Integer> queue = new LinkedList<>();
        for (int i = 0; i < n; i++) {
            if (inDegree[i] == 0) {
                res.add(i);
            }
        }
        return res;
    }
}
Python
class Solution(object):
    def findSmallestSetOfVertices(self, n, edges):
        """
        :type n: int
        :type edges: List[List[int]]
        :rtype: List[int]
        """
        # 初始化入度数组
        in_degree = [0] * n
        
        # 构建入度数组
        for edge in edges:
            in_degree[edge[1]] += 1
        
        # 找出所有入度为 0 的节点
        return [i for i in range(n) if in_degree[i] == 0]
C++
class Solution {
public:
    vector<int> findSmallestSetOfVertices(int n, vector<vector<int>>& edges) {
        // 初始化入度数组
        vector<int> inDegree(n, 0);

        // 构建入度数组
        for (const auto& edge : edges) {
            inDegree[edge[1]]++;
        }

        // 找出所有入度为 0 的节点
        vector<int> result;
        for (int i = 0; i < n; ++i) {
            if (inDegree[i] == 0) {
                result.push_back(i);
            }
        }

        return result;
    }
};

207. 课程表

🪸题目描述

在这里插入图片描述

🪷核心思路

这是一道经典的图是否有环的问题,可以通过 Kahn算法DFS 判断环的存在。

利用 入度表 + 广度优先搜索(BFS) 实现拓扑排序。

比上一题多了一步的就是加了一个邻接表,目的就是把两个点的有向连接(图二)表示出来进行BFS遍历求得结果。

在这里插入图片描述

🌿代码实现

Java
class Solution {
    public boolean canFinish(int numCourses, int[][] prerequisites) {
        // 入度数组,表示每个课程被依赖的次数
        int[] inDegree = new int[numCourses];
        // 图的邻接表表示
        List<List<Integer>> adjacency = new ArrayList<>();
        for (int i = 0; i < numCourses; i++) {
            adjacency.add(new ArrayList<>());
        }
        // 构建图和入度数组
        for (int[] pair : prerequisites) {
            inDegree[pair[0]]++;
            // 每个课程(节点)都有一个列表,列表中存储的是所有依赖于该课程的其他课程(即该课程是其他课程的先修课程)
            adjacency.get(pair[1]).add(pair[0]);
        }

        // 将所有 入度为 0 的课程加入队列,表示这些课程可以直接学习,无需先修课程。
        Queue<Integer> queue = new LinkedList<>();
        for (int i = 0; i < numCourses; i++) {
            if (inDegree[i] == 0) {
                queue.offer(i);
            }
        }

        // BFS 遍历
        int count = 0; // 记录已完成的课程数量
        while (!queue.isEmpty()) {
            int course = queue.poll();
            count++;
            for (int nextCourse : adjacency.get(course)) {
                inDegree[nextCourse]--;
                // 添加接下来 入度为0 的元素
                if (inDegree[nextCourse] == 0) {
                    queue.offer(nextCourse);
                }
            }
        }

        // 当 BFS 结束时,如果拓扑排序数组中的课程数小于总课程数,说明图中存在环,无法完成所有课程。这时,返回空数组 []
        return count == numCourses;
    }
}
Python
class Solution(object):
    def canFinish(self, numCourses, prerequisites):
        """
        :type numCourses: int
        :type prerequisites: List[List[int]]
        :rtype: bool
        """
        # 入度数组,表示每个课程被依赖的次数
        in_degree = [0] * numCourses
        # 图的邻接表表示
        adjacency = [[] for _ in range(numCourses)]

        # 构建图和入度数组
        for pair in prerequisites:
            in_degree[pair[0]] += 1
            adjacency[pair[1]].append(pair[0])

        # 将所有 入度为 0 的课程加入队列,表示这些课程可以直接学习,无需先修课程。
        queue = []
        for i in range(numCourses):
            if in_degree[i] == 0:
                queue.append(i)

        # BFS 遍历
        count = 0  # 记录已完成的课程数量
        while queue:
            course = queue.pop(0)
            count += 1
            for next_course in adjacency[course]:
                in_degree[next_course] -= 1
                if in_degree[next_course] == 0:
                    queue.append(next_course)

        # 如果拓扑排序中的课程数小于总课程数,说明存在环,无法完成所有课程
        return count == numCourses
C++
class Solution {
public:
    bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
        // 入度数组,表示每个课程被依赖的次数
        vector<int> inDegree(numCourses, 0);
        // 图的邻接表表示
        vector<vector<int>> adjacency(numCourses);

        // 构建图和入度数组
        for (const auto& pair : prerequisites) {
            inDegree[pair[0]]++;
            adjacency[pair[1]].push_back(pair[0]);
        }

        // 将所有 入度为 0 的课程加入队列,表示这些课程可以直接学习,无需先修课程。
        queue<int> q;
        for (int i = 0; i < numCourses; ++i) {
            if (inDegree[i] == 0) {
                q.push(i);
            }
        }

        // BFS 遍历
        int count = 0; // 记录已完成的课程数量
        while (!q.empty()) {
            int course = q.front();
            q.pop();
            count++;
            for (int nextCourse : adjacency[course]) {
                inDegree[nextCourse]--;
                if (inDegree[nextCourse] == 0) {
                    q.push(nextCourse);
                }
            }
        }

        // 如果拓扑排序中的课程数小于总课程数,说明存在环,无法完成所有课程
        return count == numCourses;
    }
};

210. 课程表 II

🪸题目描述

在这里插入图片描述

🪷核心思路

207. 课程表 类似,但需要输出一条合法的课程学习路径。我们可以直接基于拓扑排序构造学习路径

🌿代码实现

Java
class Solution {
    public int[] findOrder(int numCourses, int[][] prerequisites) {
        // 入度数组,表示每个课程被依赖的次数
        int[] inDegree = new int[numCourses];
        // 图的邻接表表示
        List<List<Integer>> adjacency = new ArrayList<>();
        for (int i = 0; i < numCourses; i++) {
            adjacency.add(new ArrayList<>());
        }
        // 构建图和入度数组
        for (int[] pair : prerequisites) {
            inDegree[pair[0]]++;
            adjacency.get(pair[1]).add(pair[0]);
        }

        // 将所有入度为 0 的课程加入队列
        Queue<Integer> queue = new LinkedList<>();
        for (int i = 0; i < numCourses; i++) {
            if (inDegree[i] == 0) {
                queue.offer(i);
            }
        }

        // 保存课程学习顺序
        int[] order = new int[numCourses];
        int index = 0; // 指向 `order` 数组的位置

        // BFS 遍历
        while (!queue.isEmpty()) {
            int course = queue.poll();
            order[index++] = course; // 将课程加入学习顺序
            for (int nextCourse : adjacency.get(course)) {
                inDegree[nextCourse]--;
                if (inDegree[nextCourse] == 0) {
                    queue.offer(nextCourse);
                }
            }
        }

        return index < numCourses ? new int[0] : order; // 返回课程学习顺序
    }
}
Python
class Solution(object):
    def findOrder(self, numCourses, prerequisites):
        """
        :type numCourses: int
        :type prerequisites: List[List[int]]
        :rtype: List[int]
        """
        # 入度数组,表示每个课程被依赖的次数
        in_degree = [0] * numCourses
        # 图的邻接表表示
        adjacency = [[] for _ in range(numCourses)]

        # 构建图和入度数组
        for pair in prerequisites:
            in_degree[pair[0]] += 1
            adjacency[pair[1]].append(pair[0])

        # 将所有入度为 0 的课程加入队列
        queue = []
        for i in range(numCourses):
            if in_degree[i] == 0:
                queue.append(i)

        # 保存课程学习顺序
        order = []
        while queue:
            course = queue.pop(0)
            order.append(course)
            for next_course in adjacency[course]:
                in_degree[next_course] -= 1
                if in_degree[next_course] == 0:
                    queue.append(next_course)

        # 如果拓扑排序未覆盖所有课程,返回空数组
        return order if len(order) == numCourses else []
C++
class Solution {
public:
    vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
        // 入度数组,表示每个课程被依赖的次数
        vector<int> inDegree(numCourses, 0);
        // 图的邻接表表示
        vector<vector<int>> adjacency(numCourses);

        // 构建图和入度数组
        for (const auto& pair : prerequisites) {
            inDegree[pair[0]]++;
            adjacency[pair[1]].push_back(pair[0]);
        }

        // 将所有入度为 0 的课程加入队列
        queue<int> q;
        for (int i = 0; i < numCourses; ++i) {
            if (inDegree[i] == 0) {
                q.push(i);
            }
        }

        // 保存课程学习顺序
        vector<int> order;
        while (!q.empty()) {
            int course = q.front();
            q.pop();
            order.push_back(course);
            for (int nextCourse : adjacency[course]) {
                inDegree[nextCourse]--;
                if (inDegree[nextCourse] == 0) {
                    q.push(nextCourse);
                }
            }
        }

        // 如果拓扑排序未覆盖所有课程,返回空数组
        return order.size() == numCourses ? order : vector<int>();
    }
};

802. 找到最终的安全状态

🪸题目描述

在这里插入图片描述

🪷核心思路

我们可以从反向图出发,寻找出度为 0 的节点(终点),并依次标记为安全。

为什么反向图能够帮助我们找到安全节点?

  1. 从安全节点开始反向查找:
  • 安全节点是指没有环的节点,因此从这些节点出发无法到达其他节点,因此它们的反向图中入度为 0
  • 一旦节点的入度为 0,意味着没有节点依赖它,它是“安全”的。
  1. 拓扑排序的过程:
  • 在反向图中,拓扑排序会找到所有的“无依赖”节点(即入度为 0 的节点),这些节点可以认为是安全的。
  • 通过拓扑排序,如果某个节点进入队列并被处理,说明它没有环,并且在反向图中是可以到达终点的。

🌿代码实现

Java
class Solution {
    public List<Integer> eventualSafeNodes(int[][] graph) {
        // 反向图 + 拓扑排序
        int n = graph.length;
        List<List<Integer>> reverseGraph = new ArrayList<>();
        int[] inDegree = new int[n];
        for (int i = 0; i < n; i++) {
            reverseGraph.add(new ArrayList<>());
        }

        for (int i = 0; i < n; i++) {
            for (int next : graph[i]) {
                reverseGraph.get(next).add(i);
                inDegree[i]++;
            }
        }
        
        // 2. 将所有入度为 0 的节点加入队列(安全节点)
        Queue<Integer> queue = new LinkedList<>();
        for (int i = 0; i < n; i++) {
            if (inDegree[i] == 0) {
                queue.offer(i);
            }
        }

        // 3. 拓扑排序
        List<Integer> safeNodes = new ArrayList<>();
        while (!queue.isEmpty()) {
            int node = queue.poll();
            safeNodes.add(node);
            for (int prev : reverseGraph.get(node)) {
                // 如果当前节点是某个节点的依赖节点,减少它的入度
                inDegree[prev]--;
                if (inDegree[prev] == 0) {
                    queue.offer(prev);  // 如果该节点的入度为 0,说明它是安全节点
                }
            }
        }
        
        // 4. 返回所有安全节点(按升序排序)
        Collections.sort(safeNodes);
        return safeNodes;
    }
}
Python
class Solution(object):
    def eventualSafeNodes(self, graph):
        """
        :type graph: List[List[int]]
        :rtype: List[int]
        """
        n = len(graph)
        reverseGraph = [[] for _ in range(n)]
        inDegree = [0] * n
        # 构建反向图并计算入度
        for i in range(n):
            for next_node in graph[i]:
                reverseGraph[next_node].append(i)
                inDegree[i] += 1
        
        # 将所有入度为 0 的节点加入队列
        queue = deque()
        for i in range(n):
            if inDegree[i] == 0:
                queue.append(i)
        
        # 拓扑排序
        safeNodes = []
        while queue:
            node = queue.popleft()
            safeNodes.append(node)
            for prev in reverseGraph[node]:
                inDegree[prev] -= 1
                if inDegree[prev] == 0:
                    queue.append(prev)
        
        # 返回所有安全节点,按升序排序
        safeNodes.sort()
        return safeNodes
C++
class Solution {
public:
    vector<int> eventualSafeNodes(vector<vector<int>>& graph) {
        int n = graph.size();
        vector<vector<int>> reverseGraph(n);
        vector<int> inDegree(n, 0);
        
        // 构建反向图和计算每个节点的入度
        for (int i = 0; i < n; ++i) {
            for (int next : graph[i]) {
                reverseGraph[next].push_back(i);  // 反向图
                inDegree[i]++;  // 计算入度
            }
        }
        
        // 将所有入度为 0 的节点加入队列
        queue<int> q;
        for (int i = 0; i < n; ++i) {
            if (inDegree[i] == 0) {
                q.push(i);
            }
        }

        // 拓扑排序
        vector<int> safeNodes;
        while (!q.empty()) {
            int node = q.front();
            q.pop();
            safeNodes.push_back(node);
            for (int prev : reverseGraph[node]) {
                if (--inDegree[prev] == 0) {
                    q.push(prev);
                }
            }
        }
        
        // 返回所有安全节点,按升序排序
        sort(safeNodes.begin(), safeNodes.end());
        return safeNodes;
    }
};

结语

通过这四道题,我们可以看到拓扑排序的强大应用:

  • 解决 依赖问题,如课程安排(207, 210)
  • 处理 图中状态分类 的问题,如安全状态(802)
  • 分析 关键点或入度特性,如找到最小的起点集合(1557)

拓扑排序不仅是一种算法,更是一种理解图结构的思维方式。在面试中,遇到类似依赖关系的题目,尝试从有向图的角度切入往往是一个很好的突破点。


如果您渴望探索更多精心挑选的高频LeetCode面试题,以及它们背后的巧妙解法,欢迎您访问我的博客,那里有我精心准备的一系列文章,旨在帮助技术爱好者们提升算法能力与编程技巧。

👉更多高频有趣LeetCode算法题

在我的博客中,每一篇文章都是我对算法世界的一次深入挖掘,不仅包含详尽的题目解析,还有我个人的心得体会、优化思路及实战经验分享。无论是准备面试还是追求技术成长,我相信这些内容都能为您提供宝贵的参考与启发。期待您的光临,让我们共同在技术之路上不断前行!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/927827.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MATLAB 离散点构建凸包,计算面积周长(88)

MATLAB 离散点构建凸包,计算面积周长(88) 一、算法介绍二、算法实现1.代码2.总结这是缘,亦是命中最美的相见!!! 一、算法介绍 给定一堆离散点云,构建二维凸包,并计算凸包的面积和周长。 凸包是由顺序顶点构成的,因此凸包也可以当作多边形,则例的面积和周长计算方法…

Matlab Simulink HDL Coder开发流程(一)— 创建HDL兼容的Simulink模型

创建HDL兼容的Simulink模型 一、使用Balnk DUT模板二、从HDL Coder库中选择模块三、为DUT开发算法/功能四、为设计创建Testbench五、仿真验证设计功能六、Simulink模型生成HDL代码 这个例子说明了如何创建一个用于生成HDL代码的Simulink模型。要创建兼容HDL代码生成的MATLAB算法…

【智商检测——DP】

题目 代码 #include <bits/stdc.h> using namespace std; const int N 1e510, M 110; int f[N][M]; int main() {int n, k;cin >> n >> k;for(int i 1; i < n; i){int x;cin >> x;f[i][0] __gcd(f[i-1][0], x);for(int j 1; j < min(i, k)…

神经网络入门实战:(九)分类问题 → 神经网络模型搭建模版和训练四步曲

(一) 神经网络模型搭建官方文档 每一层基本都有权重和偏置&#xff0c;可以仔细看官方文档。 pytorch 官网的库&#xff1a;torch.nn — PyTorch 2.5 documentation Containers库&#xff1a;用来搭建神经网络框架&#xff08;包含所有的神经网络的框架&#xff09;&#xff1b…

不同云计算网络安全等级

导读云计算的本质是服务&#xff0c;如果不能将计算资源规模化/大范围的进行共享&#xff0c;如果不能真正以服务的形式提供&#xff0c;就根本算不上云计算。 等级保护定级流程 定级是开展网络安全等级保护工作的 “基本出发点”&#xff0c;虚拟化技术使得传统的网络边界变…

langchain实现基于sql的问答

1. 数据准备 import requestsurl "https://storage.googleapis.com/benchmarks-artifacts/chinook/Chinook.db"response requests.get(url)if response.status_code 200:# Open a local file in binary write modewith open("Chinook.db", "wb&qu…

flink学习(14)—— 双流join

概述 Join:内连接 CoGroup&#xff1a;内连接&#xff0c;左连接&#xff0c;右连接 Interval Join&#xff1a;点对面 Join 1、Join 将有相同 Key 并且位于同一窗口中的两条流的元素进行关联。 2、Join 可以支持处理时间&#xff08;processing time&#xff09;和事件时…

深入学习指针(5)!!!!!!!!!!!!!!!

文章目录 1.回调函数是什么&#xff1f;2.qsort使用举例2.1使用qsort函数排序整形数据2.2使用sqort排序结构数据 3.qsort函数的模拟实现 1.回调函数是什么&#xff1f; 回调函数就是⼀个通过函数指针调⽤的函数。 如果你把函数的指针&#xff08;地址&#xff09;作为参数传递…

CEF127 编译指南 Linux篇 - 构建CEF Client(七)

1. 引言 在完成 CEF127 的编译工作后&#xff0c;我们需要了解如何正确运行编译后的程序。本文将详细介绍如何使用 CMake 构建示例程序&#xff0c;并成功运行 CEF 客户端。通过本文的指导&#xff0c;您将能够在 Linux 环境下顺利运行 CEF 应用程序。 2. 准备工作 2.1 确认…

位图的学习

一&#xff0c;位图介绍 位图&#xff08;Bitmap&#xff09;是一种用于存储图像的方式&#xff0c;它通过二维矩阵&#xff08;由像素组成&#xff09;来表示图像的每一个细节。每个像素通常对应一个特定的颜色值&#xff0c;位图的每个“位”就代表了图像的一个像素。 位图…

电脑与优傲协作机器人(实体)的TCP通讯(操作记录)

目录 一、UR通信端口 二、电脑&#xff08;客户端&#xff09;连接协作机器人&#xff08;服务端&#xff09; 1.设置网络方法 2.检查设置 3.示教器切换远程控制&#xff08;注&#xff09; 4.客户端与协作机器人建立连接 5.连接测试 三、电脑&#xff08;服务端&#…

后端 Java发送邮件 JavaMail 模版 20241128测试可用

配置授权码 依赖 <dependency><groupId>javax.mail</groupId><artifactId>javax.mail-api</artifactId><version>1.5.5</version> </dependency> <dependency><groupId>com.sun.mail</groupId><artifa…

12.2 正则表达式

object test04 {def main(args: Array[String]): Unit {//1.定义规则。写正则表达式val reg "\\d".r // \\d表示找数字//2.在目标字符串中&#xff0c;去按照这个规则去找符合的子字符串val result reg.findFirstIn("我是who&#xff0c;我的电话是&#xff…

MySQL:DDL数据定义语言

DDL(Data Definition Language)&#xff0c;数据定义语言 对数据库的常用操作 查看所有数据库 语法&#xff1a;show databases; 创建数据库 dbname&#xff1a;用户自己定义的数据库名称。 语法&#xff1a;create database [if not exists] dbname [charsetutf8]; 切换…

2024信创数据库TOP30之华为Gauss DB

近日&#xff0c;由DBC联合CIW/CIS共同发布的“2024信创数据库TOP30”榜单正式揭晓&#xff0c;汇聚了国内顶尖的数据库企业及其产品&#xff0c;成为展示中国信创领域技术实力与发展潜力的重要平台。在这份榜单中&#xff0c;华为的GaussDB凭借其卓越的技术实力、广泛的行业应…

HTML+CSS+JS制作圣诞祝福网页教程(附源码)

简介 在这个教程中&#xff0c;我们将学习如何使用HTML、CSS和JavaScript来创建一个充满节日气氛的圣诞祝福网页。这个网页将包括一个动态的圣诞树、飘落的雪花和闪烁的装饰物&#xff0c;以及一个显示“圣诞快乐&#xff01;”的消息。 准备工作 在开始之前&#xff0c;请确…

华为仓颉编程环境搭建

1、仓颉介绍 摘自华为官方&#xff1a;仓颉编程语言作为一款面向全场景应用开发的现代编程语言&#xff0c;通过现代语言特性的集成、全方位的编译优化和运行时实现、以及开箱即用的 IDE 工具链支持&#xff0c;为开发者打造友好开发体验和卓越程序性能。 其具体特性表现为&am…

朗迪锋亮相2024人因工程与智能系统交互国际会议

2024年11月28日至30日&#xff0c;2024人因工程与智能系统交互国际会议在深圳隆重举办。此次大会以推动我国人因工程学科发展为目标&#xff0c;致力于加强国际学术交流&#xff0c;深入探讨人工智能时代的智能系统交互&#xff0c;旨在培育新质生产力&#xff0c;助力经济社会…

【小白学机器学习39】如何用numpy生成总体,生成样本samples

目录 1 目的&#xff1a;研究 样本和总体之间的关系 2 先生成1个理论总体 2.0 下面是关于这一步的完整代码 2.1 一般情况下&#xff0c;我们先生成一个符合正态分布的总体 2.1.1 设置总体 &#xff0c;或者说生成一个总体 2.2 为什么一定要是一个符合正态分布的总体&…

什么是sfp,onu,​为什么PON(​俗称“光猫”​)模块使用SC光纤接口

在现代网络设备中&#xff0c;我们经常会看到SFP或SFP接口的身影&#xff0c;这些接口有时被简称为光口&#xff0c;但这个称呼并不严谨。有些厂商则称之为多功能口或多用途口&#xff0c;然而这对于不了解的人来说可能还是一头雾水。SFP&#xff0c;即Small Form-Factor Plugg…