代码随想录算法训练营第十八天|235.二叉搜索树的最近公共祖先,701.二叉搜索树中的插入操作,450.删除二叉搜索树节点

235.二叉搜索树的最近公共祖先

701.二叉搜索树中的插入操作

450.删除二叉搜索树节点 

 235.二叉搜索树的最近公共祖先

给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

例如,给定如下二叉搜索树:  root = [6,2,8,0,4,7,9,null,null,3,5]

示例 1:

输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
输出: 6 
解释: 节点 2 和节点 8 的最近公共祖先是 6。

示例 2:

输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
输出: 2
解释: 节点 2 和节点 4 的最近公共祖先是 2, 因为根据定义最近公共祖先节点可以为节点本身。

说明:

  • 所有节点的值都是唯一的。
  • p、q 为不同节点且均存在于给定的二叉搜索树中。

 

在二叉搜索树(BST)中找到两个节点pq的最低公共祖先(LCA)。在二叉搜索树中,最低公共祖先的特点是它的值在pq的值之间(包括等于pq的情况)。如果pq的值都小于当前节点,那么它们的公共祖先位于当前节点的左子树;如果它们的值都大于当前节点,那么它们的公共祖先位于当前节点的右子树。如果pq分别位于当前节点的两侧,那么当前节点就是它们的最低公共祖先。

代码逻辑

  • 首先检查当前节点是否为NULL,如果是,则返回NULL
  • 然后,如果pq的值都小于当前节点的值,递归地在当前节点的左子树中查找。
  • 如果pq的值都大于当前节点的值,递归地在当前节点的右子树中查找。
  • 如果上述两种情况都不满足(即当前节点的值介于pq的值之间),说明找到了最低公共祖先,返回当前节点。

这个实现利用了BST的性质来优化搜索过程,避免了不必要的遍历。

C++ 

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/class Solution {private:TreeNode* traversal(TreeNode* cur, TreeNode* p, TreeNode* q) {if (cur == NULL) return cur;// 中if (cur->val > p->val && cur->val > q->val) {   // 左TreeNode* left = traversal(cur->left, p, q);if (left != NULL) {return left;}}if (cur->val < p->val && cur->val < q->val) {   // 右TreeNode* right = traversal(cur->right, p, q);if (right != NULL) {return right;}}return cur;}
public:TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {return traversal(root, p, q);}
};

python

class TreeNode:def __init__(self, val=0, left=None, right=None):self.val = valself.left = leftself.right = rightclass Solution:def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':# 如果当前节点为空,或者p、q之一就是当前节点,则直接返回当前节点if not root or root == p or root == q:return root# 根据BST的性质在左子树或右子树中查找if p.val < root.val and q.val < root.val:# p和q都在当前节点的左侧return self.lowestCommonAncestor(root.left, p, q)elif p.val > root.val and q.val > root.val:# p和q都在当前节点的右侧return self.lowestCommonAncestor(root.right, p, q)else:# 当前节点就是p和q的最低公共祖先return root

迭代法

在二叉搜索树(BST)中查找两个节点的最低公共祖先(LCA)时,可以使用迭代法代替递归来减少空间复杂度。迭代法的核心思想是利用BST的性质:对于树中的任意节点y,如果pq的值都小于y,则pq都在y的左子树中;如果pq的值都大于y,则pq都在y的右子树中;否则,y就是pq的最低公共祖先。

C++

#include <iostream>struct TreeNode {int val;TreeNode *left;TreeNode *right;TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};class Solution {
public:TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {// 当前节点初始化为根节点TreeNode* current = root;while (current) {// 如果p和q的值都小于当前节点的值,则在左子树中查找if (p->val < current->val && q->val < current->val) {current = current->left;}// 如果p和q的值都大于当前节点的值,则在右子树中查找else if (p->val > current->val && q->val > current->val) {current = current->right;}// 否则,当前节点就是LCAelse {return current;}}return nullptr;}
};

python

class TreeNode:def __init__(self, val=0, left=None, right=None):self.val = valself.left = leftself.right = rightclass Solution:def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':# 当前节点初始化为根节点current = rootwhile current:# 如果p和q的值都小于当前节点的值,则在左子树中查找if p.val < current.val and q.val < current.val:current = current.left# 如果p和q的值都大于当前节点的值,则在右子树中查找elif p.val > current.val and q.val > current.val:current = current.right# 否则,当前节点就是LCAelse:return currentreturn None

701.二叉搜索树中的插入操作

给定二叉搜索树(BST)的根节点 root 和要插入树中的值 value ,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。

注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回 任意有效的结果 。

示例 1:

输入:root = [4,2,7,1,3], val = 5
输出:[4,2,7,1,3,5]
解释:另一个满足题目要求可以通过的树是:

示例 2:

输入:root = [40,20,60,10,30,50,70], val = 25
输出:[40,20,60,10,30,50,70,null,null,25]

示例 3:

输入:root = [4,2,7,1,3,null,null,null,null,null,null], val = 5
输出:[4,2,7,1,3,5]

提示:

  • 树中的节点数将在 [0, 104]的范围内。
  • -108 <= Node.val <= 108
  • 所有值 Node.val 是 独一无二 的。
  • -108 <= val <= 108
  • 保证 val 在原始BST中不存在。

将一个值插入到二叉搜索树(BST)中,并保持BST的性质。代码中使用了递归方法来找到合适的位置插入新节点。如果树为空,就直接创建一个新节点作为根节点。如果树不为空,递归遍历树直到找到合适的插入位置,然后根据值的大小插入到左子树或右子树。

代码逻辑

  1. 递归遍历:通过traversal函数递归遍历BST,parent变量用于记录当前节点的父节点,以便在找到插入位置时可以直接插入。
  2. 插入新节点:当到达空位置(cur == NULL)时,根据新节点的值与父节点的值的比较结果,决定是将新节点作为左子节点还是右子节点插入。
  3. 树为空的特殊处理:如果BST为空(root == NULL),则直接创建新节点作为根节点。

然而,原始C++代码实现中有一个潜在问题:parent变量的初始值被设置为一个新的TreeNode实例,这个实例并未被真正用作树的一部分,可能会导致内存泄漏或不必要的内存分配。在实际插入操作中,如果根节点非空,parent变量的初始值并未被使用。

C++

class Solution {
private:TreeNode* parent;void traversal(TreeNode* cur, int val) {if (cur == NULL) {TreeNode* node = new TreeNode(val);if (val > parent->val) parent->right = node;else parent->left = node;return;}parent = cur;if (cur->val > val) traversal(cur->left, val);if (cur->val < val) traversal(cur->right, val);return;}public:TreeNode* insertIntoBST(TreeNode* root, int val) {parent = new TreeNode(0);if (root == NULL) {root = new TreeNode(val);}traversal(root, val);return root;}
};

python

class TreeNode:def __init__(self, val=0, left=None, right=None):self.val = valself.left = leftself.right = rightclass Solution:def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode:if not root:return TreeNode(val)def insert(node, val):if not node:return TreeNode(val)if val > node.val:node.right = insert(node.right, val)else:node.left = insert(node.left, val)return nodereturn insert(root, val)

针对C++实现的优化主要集中在避免使用递归来降低空间复杂度,并提高代码执行效率。通过迭代方法寻找正确的插入位置

  • 这个版本的代码使用了迭代方法来寻找新节点的正确插入位置。这种方法避免了递归调用,减少了函数调用栈的使用。
  • 通过迭代遍历树,我们检查新值应该插入到当前节点的左侧还是右侧。如果找到一个空位置(即current->leftcurrent->rightnullptr),就在那里插入新节点。
  • 这种方法保持了二叉搜索树的特性,同时提高了代码的执行效率,特别是在处理大树时。

 

C++

#include <iostream>struct TreeNode {int val;TreeNode *left;TreeNode *right;TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};class Solution {
public:TreeNode* insertIntoBST(TreeNode* root, int val) {// 如果树为空,直接创建并返回新节点作为根节点if (root == nullptr) {return new TreeNode(val);}// 使用迭代寻找正确的插入位置TreeNode* current = root; // 当前节点while (true) {// 如果插入的值大于当前节点的值if (val > current->val) {// 如果当前节点的右子节点为空,则在此位置插入新节点if (current->right == nullptr) {current->right = new TreeNode(val);break; // 插入后退出循环} else {// 否则继续向右子树移动current = current->right;}} else {// 如果当前节点的左子节点为空,则在此位置插入新节点if (current->left == nullptr) {current->left = new TreeNode(val);break; // 插入后退出循环} else {// 否则继续向左子树移动current = current->left;}}}return root; // 返回未修改的根节点}
};

python 

class TreeNode:def __init__(self, val=0, left=None, right=None):self.val = valself.left = leftself.right = rightclass Solution:def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode:# 如果根节点为空,直接返回新创建的节点if not root:return TreeNode(val)# 定位插入位置current = rootwhile current:# 如果插入的值大于当前节点的值if val > current.val:# 如果右子节点为空,插入新节点并退出循环if not current.right:current.right = TreeNode(val)break# 否则,向右子树移动else:current = current.right# 如果插入的值小于或等于当前节点的值else:# 如果左子节点为空,插入新节点并退出循环if not current.left:current.left = TreeNode(val)break# 否则,向左子树移动else:current = current.leftreturn root

450.删除二叉搜索树节点

给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。

一般来说,删除节点可分为两个步骤:

  1. 首先找到需要删除的节点;
  2. 如果找到了,删除它。

示例 1:

输入:root = [5,3,6,2,4,null,7], key = 3
输出:[5,4,6,2,null,null,7]
解释:给定需要删除的节点值是 3,所以我们首先找到 3 这个节点,然后删除它。
一个正确的答案是 [5,4,6,2,null,null,7], 如下图所示。
另一个正确答案是 [5,2,6,null,4,null,7]。

示例 2:

输入: root = [5,3,6,2,4,null,7], key = 0
输出: [5,3,6,2,4,null,7]
解释: 二叉树不包含值为 0 的节点

示例 3:

输入: root = [], key = 0
输出: []

实现了在二叉搜索树(BST)中删除一个具有特定键值的节点的功能,并且处理了多种情况,确保删除操作后,树仍然保持BST的性质。

功能分析

  1. 节点未找到:如果当前节点为空,则表示未找到要删除的节点,直接返回nullptr
  2. 找到节点:如果找到了要删除的节点(root->val == key),根据其子节点的情况有以下几种处理方式:
    • 叶子节点:如果节点是叶子节点(没有子节点),则直接删除该节点,并返回nullptr
    • 单子节点:如果节点只有一个子节点(左子节点或右子节点),则删除该节点,并用其子节点替代它,返回替代后的子节点。
    • 双子节点:如果节点有两个子节点,则找到右子树中最左侧的节点(右子树中的最小节点),将要删除节点的左子树接到这个最左侧节点的左侧,然后删除节点,并用其右子节点替代它。
  3. 递归删除:如果要删除的节点值大于当前节点值,递归删除左子树中的节点;如果要删除的节点值小于当前节点值,递归删除右子树中的节点。

C++

class Solution {
public:TreeNode* deleteNode(TreeNode* root, int key) {if (root == nullptr) return root; // 第一种情况:没找到删除的节点,遍历到空节点直接返回了if (root->val == key) {// 第二种情况:左右孩子都为空(叶子节点),直接删除节点, 返回NULL为根节点if (root->left == nullptr && root->right == nullptr) {///! 内存释放delete root;return nullptr;}// 第三种情况:其左孩子为空,右孩子不为空,删除节点,右孩子补位 ,返回右孩子为根节点else if (root->left == nullptr) {auto retNode = root->right;///! 内存释放delete root;return retNode;}// 第四种情况:其右孩子为空,左孩子不为空,删除节点,左孩子补位,返回左孩子为根节点else if (root->right == nullptr) {auto retNode = root->left;///! 内存释放delete root;return retNode;}// 第五种情况:左右孩子节点都不为空,则将删除节点的左子树放到删除节点的右子树的最左面节点的左孩子的位置// 并返回删除节点右孩子为新的根节点。else {TreeNode* cur = root->right; // 找右子树最左面的节点while(cur->left != nullptr) {cur = cur->left;}cur->left = root->left; // 把要删除的节点(root)左子树放在cur的左孩子的位置TreeNode* tmp = root;   // 把root节点保存一下,下面来删除root = root->right;     // 返回旧root的右孩子作为新rootdelete tmp;             // 释放节点内存(这里不写也可以,但C++最好手动释放一下吧)return root;}}if (root->val > key) root->left = deleteNode(root->left, key);if (root->val < key) root->right = deleteNode(root->right, key);return root;}
};

python

class TreeNode:def __init__(self, val=0, left=None, right=None):self.val = valself.left = leftself.right = rightclass Solution:def deleteNode(self, root: TreeNode, key: int) -> TreeNode:if not root:return None  # 没找到删除的节点if root.val == key:if not root.left and not root.right:return None  # 叶子节点,直接删除elif not root.left:return root.right  # 只有右子节点elif not root.right:return root.left  # 只有左子节点else:cur = root.rightwhile cur.left:cur = cur.left  # 找到右子树最左侧的节点cur.left = root.left  # 将要删除节点的左子树接到cur的左侧return root.right  # 删除节点,返回右子节点elif root.val > key:root.left = self.deleteNode(root.left, key)else:root.right = self.deleteNode(root.right, key)return root

优化删除节点的代码主要关注减少代码复杂度和提高执行效率。在二叉搜索树(BST)中删除节点时,特别是当目标节点有两个子节点的情况下,一个常见的优化方法是寻找目标节点右子树的最小节点(或左子树的最大节点),然后用它来替代目标节点的值,并在该子树中递归删除那个替代的节点。这种方法避免了直接操作树的结构,只需修改节点的值,简化了节点替换的逻辑。

C++

#include <iostream>struct TreeNode {int val;TreeNode *left;TreeNode *right;TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};class Solution {
public:TreeNode* deleteNode(TreeNode* root, int key) {if (!root) return nullptr;if (root->val == key) {if (!root->left) return root->right;if (!root->right) return root->left;TreeNode* minNode = root->right;while (minNode->left) minNode = minNode->left;root->val = minNode->val;  // 替换值root->right = deleteNode(root->right, root->val);  // 删除替代节点} else if (root->val > key) {root->left = deleteNode(root->left, key);} else {root->right = deleteNode(root->right, key);}return root;}
};

 python

class TreeNode:def __init__(self, val=0, left=None, right=None):self.val = valself.left = leftself.right = rightclass Solution:def deleteNode(self, root: TreeNode, key: int) -> TreeNode:if not root:return Noneif root.val == key:if not root.left:  # 只有右子节点或无子节点return root.rightif not root.right:  # 只有左子节点return root.left# 有两个子节点,找右子树的最小节点替代删除节点minNode = root.rightwhile minNode.left:minNode = minNode.leftroot.val = minNode.val  # 替换值root.right = self.deleteNode(root.right, root.val)  # 删除替代节点elif root.val > key:root.left = self.deleteNode(root.left, key)else:root.right = self.deleteNode(root.right, key)return root

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

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

相关文章

基于shp数据制作3DTiles建筑白膜

经纬管网建模系统MagicPipe3D&#xff0c;本地离线参数化构建地下管网、建筑三维模型&#xff0c;输出标准3DTiles服务、Obj模型等格式&#xff0c;支持Cesium、Unreal、Unity、Osg等引擎加载进行三维可视化、语义查询、专题分析。欢迎下载试用&#xff1a;http://www.magic3d.…

Spring Boot 笔记 023 注册页面

1.1 request.js请求工具 //定制请求的实例//导入axios npm install axios import axios from axios; //定义一个变量,记录公共的前缀 , baseURL const baseURL /api; const instance axios.create({baseURL})//添加响应拦截器 instance.interceptors.response.use(result…

npm ERR! code CERT_HAS_EXPIRED:解决证书过期问题

转载&#xff1a;npm ERR! code CERT_HAS_EXPIRED&#xff1a;解决证书过期问题_npm err! code cert_has_expired npm err! errno cert-CSDN博客 npm config set registry http://registry.cnpmjs.org npm config set registry http://registry.npm.taobao.org

JVM-JVM中对象的结构

对象内存布局 对象里的三个区&#xff1a; 对象头&#xff08;Header&#xff09;&#xff1a;Java对象头占8byte。如果是数组则占12byte。因为JVM里数组size需要使用4byte存储。 标记字段MarkWord&#xff1a; 用于存储对象自身的运行时数据&#xff0c;它是synchronized实现轻…

内核移植学习

内核移植 内核移植就是指将RT-Thread内核在不同的芯片架构、不同的板卡上运行起来。 移植可分为CPU架构移植和BSP板级支持包移植两部分。 CPU架构移植 在嵌入式领域有多种不同CPU架构&#xff0c;例如Cortex-M、ARM920T、MIPS32、RISC-V等等。 为了使RT-Thread能够在不同C…

最新 Vue3、TypeScript、组合式API、setup语法糖 学习笔记

最新 Vue3、TypeScript、组合式API、setup语法糖 学习笔记 1、创建 Vue3 工程基于 `vue-cli` 创建(基于webpack实现)基于 `vite` 创建(推荐)2、Vue3 项目开发 `vscode` 插件推荐3、`Vue3` 核心语法【optionsAPI】与【CompositionAPI】Options API 的弊端Composition API 的…

提取游戏音频文件.bnk

提取游戏音频文件.bnk 什么是.bnk准备Wwise-Unpacker工具使用Wwise-Unpacker工具总结 什么是.bnk .bnk其实是一种对音频的加密方式&#xff0c;一个.bnk文件中通常包含了多个语音文件&#xff0c;一般可以使用Wwise-Unpacker来解码.bnk格式文件 准备Wwise-Unpacker工具 Wwis…

《Go 简易速速上手小册》第7章:包管理与模块(2024 最新版)

文章目录 7.1 使用 Go Modules 管理依赖 - 掌舵向未来7.1.1 基础知识讲解7.1.2 重点案例&#xff1a;Web 服务功能描述实现步骤扩展功能 7.1.3 拓展案例 1&#xff1a;使用数据库功能描述实现步骤扩展功能 7.1.4 拓展案例 2&#xff1a;集成 Redis 缓存功能描述实现步骤扩展功能…

OpenAI 发布文生视频大模型 Sora,AI 视频要变天了,视频创作重新洗牌!AGI 还远吗?

一、一觉醒来&#xff0c;AI 视频已变天 早上一觉醒来&#xff0c;群里和朋友圈又被刷屏了。 今年开年 AI 界最大的震撼事件&#xff1a;OpenAI 发布了他们的文生视频大模型 Sora。 OpenAI 文生视频大模型 Sora 的横空出世&#xff0c;预示着 AI 视频要变天了&#xff0c;视…

python 笔记:shapely(形状篇)

主要是点&#xff08;point&#xff09;、线&#xff08;linestring&#xff09;、面&#xff08;surface&#xff09; 1 基本方法和属性 object.area 返回对象的面积&#xff08;浮点数&#xff09; object.bounds 返回一个&#xff08;minx, miny, maxx, maxy&#xff09;元…

MySQL - 增量同步和全量同步

增量同步和全量同步是数据同步过程中常用的两种方式&#xff0c;它们在定义、区别以及适用场景上有一些明显的差异。 一、定义 增量同步是指在数据同步中仅同步更新或新增的数据&#xff0c;而不包括已经同步过的数据。全量同步则是指将所有数据进行一次完整的同步&#xff0c…

网络原理 - HTTP/HTTPS(3)

HTTP请求 认识请求"报头" header的整体的格式也是"键值对"的结构. 每个键值对占一行,键和值之间使用分号进行分割. 报头的种类有很多,此处仅介绍几个常见的. Host 表示服务器主机的地址和端口.(Host和URL中的ip地址端口啥的,绝大部分情况下都是一样的,少…

智慧城市驿站:智慧公厕升级版,打造现代化城市生活的便捷配套

随着城市化进程的加速&#xff0c;人们对城市生活质量的要求也越来越高。作为智慧城市建设的一项重要组成部分&#xff0c;多功能城市智慧驿站应运而生。它集合了信息技术、设计美学、结构工艺、系统集成、环保节能等多个亮点&#xff0c;将现代科技与城市生活相融合&#xff0…

qt - 19种精美软件样式

qt - 19种精美软件样式 一、效果演示二、核心程序三、下载链接 一、效果演示 二、核心程序 #include "mainwindow.h"#include <QtAdvancedStylesheet.h> #include <QmlStyleUrlInterceptor.h>#include "ui_mainwindow.h" #include <QDir&g…

OpenCV 4基础篇| 色彩空间类型转换

目录 1. 色彩空间基础2. 色彩空间类型2.1 GRAY 色彩空间2.2 BGR 色彩空间2.3 CMY(K) 色彩空间2.4 XYZ 色彩空间2.5 HSV 色彩空间2.6 HLS 色彩空间2.7 CIEL*a*b* 色彩空间2.8 CIEL*u*v* 色彩空间2.9 YCrCb 色彩空间 3. 类型转换函数3.1 cv2.cvtColor3.2 cv2.inRange 1. 色彩空间…

你真的了解—————NumPy吗

&#x1f308;个人主页&#xff1a;小田爱学编程 &#x1f525; 系列专栏&#xff1a;opencv &#x1f3c6;&#x1f3c6;关注博主&#xff0c;随时获取更多关于IT的优质内容&#xff01;&#x1f3c6;&#x1f3c6; &#x1f600;欢迎来到小田代码世界~ &#x1f601; 喜欢的…

Linux 基础/子目录分配/文件路径

在Linux系统中&#xff0c;整个系统只具有一个根目录“/”&#xff0c;用斜杠表示。根目录是整个文件系统的顶层目录&#xff0c;在他下面可以创建其他的目录和文件。 Linux中的子目录分配&#xff1a; /bin - 基本命令的二进制文件&#xff0c;这些命令可供所有用户使用&am…

行人重识别综述

Deep Learning for Person Re-identification: A Survey and Outlook 论文地址https://arxiv.org/pdf/2001.04193 1. 摘要 we categorize it into the closed-world and open-world settings. closed-world&#xff1a;学术环境下 open-world &#xff1a;实际应用场景下 2…

Linux 驱动开发基础知识——APP 怎么读取按键值(十二)

个人名片&#xff1a; &#x1f981;作者简介&#xff1a;学生 &#x1f42f;个人主页&#xff1a;妄北y &#x1f427;个人QQ&#xff1a;2061314755 &#x1f43b;个人邮箱&#xff1a;2061314755qq.com &#x1f989;个人WeChat&#xff1a;Vir2021GKBS &#x1f43c;本文由…

【Linux】Linux权限

Linux权限 Linux下用户的分类切换用户su 和 su - 的区别 对命令提权 权限的概念Linux权限管理文件访问者的分类&#xff08;人&#xff09;1️⃣拥有者u→user2️⃣其他人o→others3️⃣所属组group 文件类型和访问权限&#xff08;事物属性&#xff09;文件文件类型文件的基本…