当前位置: 首页 > news >正文

Day 21代码|随想录| 二叉树完结撒花,今日刷题669.修剪二叉搜索树、108.将有序数组转换为二叉搜索树、538.吧二叉搜索树转换为累加树

提示:DDU,供自己复习使用。欢迎大家前来讨论~

文章目录

  • 二叉树 Part06
  • 二、题目
    • 题目一:669.修剪二叉搜索树
      • 解题思路:
      • 递归法
      • 迭代法:
    • 题目二: 108.将有序数组转换为二叉搜索树
      • 解题思路
      • 递归法:
      • 迭代法
    • 题目三:538.把二叉搜索树转换为累加树
      • 解题思路:
      • 递归法
      • 迭代法
    • 二叉树总结篇
      • 二叉树的理论基础
      • 二叉树的遍历方式
      • 求二叉树的属性
      • 二叉树的改造与修改
      • 求二叉搜索树的属性
      • 二叉树公共祖先问题
      • 二叉搜索树的修改与改造
  • 总结


二叉树 Part06

二、题目

题目一:669.修剪二叉搜索树

[669. 修剪二叉搜索树](https://leetcode.cn/problems/minimum-absolute-difference-in-bst/)

解题思路:

错误的思路:

直接想法就是:递归处理,然后遇到 root->val < low || root->val > high 的时候直接return NULL,一波修改,干净利落。

可以写出以下代码:

class Solution {
public:TreeNode* trimBST(TreeNode* root, int low, int high) {if (root == nullptr || root->val < low || root->val > high) return nullptr;root->left = trimBST(root->left, low, high);root->right = trimBST(root->right, low, high);return root;}
};

note:

但是会忽略掉删除节点的右子树,可能会存在符合的节点,但是上面的代码直接删除了,所以是不可行的。下图就是示例图:

669.修剪二叉搜索树

从图中可以看出需要重构二叉树,想想是不是本题就有点复杂了。

其实不用重构那么复杂。在上图中我们发现节点0并不符合区间要求,那么将节点0的右孩子 节点2 直接赋给 节点3的左孩子就可以了(就是把节点0从二叉树中移除),如图:

669.修剪二叉搜索树1

递归法

  • 确定递归函数的参数以及返回值

    这里我们为什么需要返回值呢?

    因为是要遍历整棵树,做修改,其实不需要返回值也可以,我们也可以完成修剪(其实就是从二叉树中移除节点)的操作。

    但是有返回值,更方便,可以通过递归函数的返回值来移除节点。

    TreeNode* trimBST(TreeNode* root, int low, int high)
    
  • 确定终止条件

    修剪的操作并不是在终止条件上进行的,所以就是遇到空节点返回就可以了。

    if (root == nullptr ) return nullptr;
    
  • 确定单层递归的逻辑

    如果root(当前节点)的元素小于low的数值,那么应该递归右子树,并返回右子树符合条件的头结点。

    if (root->val < low) {TreeNode* right = trimBST(root->right, low, high); // 寻找符合区间[low, high]的节点return right;
    }// 同理如果root(当前节点)的元素大于high的,那么应该递归左子树,并返回左子树符合条件的头结点。
    if (root->val > high) {TreeNode* left = trimBST(root->left, low, high); // 寻找符合区间[low, high]的节点return left;
    }    
    

    接下来要将下一层处理完左子树的结果赋给root->left,处理完右子树的结果赋给root->right。

    最后返回root节点,代码如下:

    这里可能是子树里面还有不符合要求的节点,所以还是要遍历一下的。

    root->left = trimBST(root->left, low, high); // root->left接入符合条件的左孩子
    root->right = trimBST(root->right, low, high); // root->right接入符合条件的右孩子
    return root;
    

    Q:多余的节点究竟是如何从二叉树中移除的呢?

    在回顾一下上面的代码,针对下图中二叉树的情况:

    669.修剪二叉搜索树1

    如下代码相当于把节点0的右孩子(节点2)返回给上一层,

    if (root->val < low) {TreeNode* right = trimBST(root->right, low, high); // 寻找符合区间[low, high]的节点return right;
    }
    

    然后如下代码相当于用节点3的左孩子 把下一层返回的 节点0的右孩子(节点2) 接住。

    root->left = trimBST(root->left, low, high);
    

    此时节点3的左孩子就变成了节点2,将节点0从二叉树中移除了。

完整代码如下:

class Solution {
public:TreeNode* trimBST(TreeNode* root, int low, int high) {if (root == nullptr ) return nullptr;if (root->val < low) {TreeNode* right = trimBST(root->right, low, high); // 寻找符合区间[low, high]的节点return right;}if (root->val > high) {TreeNode* left = trimBST(root->left, low, high); // 寻找符合区间[low, high]的节点return left;}root->left = trimBST(root->left, low, high); // root->left接入符合条件的左孩子root->right = trimBST(root->right, low, high); // root->right接入符合条件的右孩子return root;}
};

精简之后:

class Solution {
public:TreeNode* trimBST(TreeNode* root, int low, int high) {if (root == nullptr) return nullptr;if (root->val < low) return trimBST(root->right, low, high);if (root->val > high) return trimBST(root->left, low, high);root->left = trimBST(root->left, low, high);root->right = trimBST(root->right, low, high);return root;}
};

迭代法:

因为二叉搜索树的有序性,不需要使用栈模拟递归的过程。

在剪枝的时候,可以分为三步:

  • 将root移动到[L, R] 范围内,注意是左闭右闭区间
  • 剪枝左子树
  • 剪枝右子树
class Solution {
public:TreeNode* trimBST(TreeNode* root, int L, int R) {if (!root) return nullptr;// 处理头结点,让root移动到[L, R] 范围内,注意是左闭右闭while (root != nullptr && (root->val < L || root->val > R)) {if (root->val < L) root = root->right; // 小于L往右走else root = root->left; // 大于R往左走}TreeNode *cur = root;// 此时root已经在[L, R] 范围内,处理左孩子元素小于L的情况while (cur != nullptr) {while (cur->left && cur->left->val < L) {cur->left = cur->left->right;}cur = cur->left;}cur = root;// 此时root已经在[L, R] 范围内,处理右孩子大于R的情况while (cur != nullptr) {while (cur->right && cur->right->val > R) {cur->right = cur->right->left;}cur = cur->right;}return root;}
};

小结:

题目二: 108.将有序数组转换为二叉搜索树

108. 将有序数组转换为二叉搜索树

解题思路

  • 本质就是寻找分割点,分割点作为当前节点,然后递归左区间和右区间
  • 因为有序数组构造二叉搜索树,寻找分割点就比较容易了。
  • 分割点就是数组中间位置的节点。

Q:如果数组长度为偶数,中间节点有两个,取哪一个?

​ 取哪一个都可以,只不过构成了不同的平衡二叉搜索树。

例如:输入:[-10,-3,0,5,9]

如下两棵树,都是这个数组的平衡二叉搜索树:

108.将有序数组转换为二叉搜索树

如果要分割的数组长度为偶数的时候,中间元素为两个,是取左边元素 就是树1,取右边元素就是树2。

这也是题目中强调答案不是唯一的原因。

递归法:

  1. 确定递归函数的返回值及参数

    这里定义的是左闭右闭区间,在不断分割的过程中,也会坚持左闭右闭的区间,这又涉及之前讲过的循环不变量

    // 左闭右闭区间[left, right]
    TreeNode* traversal(vector<int>& nums, int left, int right)
    
  2. 确定递归终止条件

    这里定义的是左闭右闭的区间,所以当区间 left > right的时候,就是空节点了。

    if (left > right) return nullptr;
    
  3. 确定单层递归的逻辑

​ 首先取数组中间元素的位置,不难写出int mid = (left + right) / 2;这么写其实有一个问题,就是数值越界,例如left和right都是最大int,这么操作就越界了,在二分法中尤其需要注意!

​ **note:**所以可以这么写:int mid = left + ((right - left) / 2);

  • int mid = left + ((right - left) / 2);  //首先取数组中间元素的位置
    TreeNode* root = new TreeNode(nums[mid]); //取了中间位置,就开始以中间位置的元素构造节点
    root->left = traversal(nums, left, mid - 1); //接着划分区间,root的左孩子接住下一层左区间的构造节点,右孩子接住下一层右区间构造的节点。
    root->right = traversal(nums, mid + 1, right);
    return root;
    

这里int mid = left + ((right - left) / 2);的写法相当于是如果数组长度为偶数,中间位置有两个元素,取靠左边的。

整体C++代码如下:

class Solution {
private:TreeNode* traversal(vector<int>& nums, int left, int right) {if (left > right) return nullptr;int mid = left + ((right - left) / 2);TreeNode* root = new TreeNode(nums[mid]);root->left = traversal(nums, left, mid - 1);root->right = traversal(nums, mid + 1, right);return root;}
public:TreeNode* sortedArrayToBST(vector<int>& nums) {TreeNode* root = traversal(nums, 0, nums.size() - 1);return root;}
};

注意:在调用traversal的时候传入的left和right为什么是0和nums.size() - 1,因为定义的区间为左闭右闭

迭代法

迭代法可以通过三个队列来模拟,一个队列放遍历的节点,一个队列放左区间下标,一个队列放右区间下标

模拟的就是不断分割的过程,C++代码如下:

class Solution {
public:TreeNode* sortedArrayToBST(vector<int>& nums) {if (nums.size() == 0) return nullptr;TreeNode* root = new TreeNode(0);   // 初始根节点queue<TreeNode*> nodeQue;           // 放遍历的节点queue<int> leftQue;                 // 保存左区间下标queue<int> rightQue;                // 保存右区间下标nodeQue.push(root);                 // 根节点入队列leftQue.push(0);                    // 0为左区间下标初始位置rightQue.push(nums.size() - 1);     // nums.size() - 1为右区间下标初始位置while (!nodeQue.empty()) {TreeNode* curNode = nodeQue.front();nodeQue.pop();int left = leftQue.front(); leftQue.pop();int right = rightQue.front(); rightQue.pop();int mid = left + ((right - left) / 2);curNode->val = nums[mid];       // 将mid对应的元素给中间节点if (left <= mid - 1) {          // 处理左区间curNode->left = new TreeNode(0);nodeQue.push(curNode->left);leftQue.push(left);rightQue.push(mid - 1);}if (right >= mid + 1) {         // 处理右区间curNode->right = new TreeNode(0);nodeQue.push(curNode->right);leftQue.push(mid + 1);rightQue.push(right);}}return root;}
};

小结:

  1. 递归思路:提到了递归方法的核心思路是不断进行中间分割,然后递归地处理左区间和右区间,这也是一种分治策略。
  2. 递归函数的返回值:通过递归函数的返回值来增删二叉树是常规操作。
  3. 循环不变量的重要性:在定义区间的过程中,再次强调了循环不变量的重要性,这可能是在递归或迭代过程中保持逻辑一致性的关键。
  4. 迭代方法:这实际上是模拟取中间元素,然后不断分割去构造二叉树的过程。
  5. 递归与迭代的比较:虽然递归方法可能更直观,但迭代方法提供了另一种解决问题的途径,特别是在某些情况下可能更高效或更适合某些应用场景。

题目三:538.把二叉搜索树转换为累加树

538. 把二叉搜索树转换为累加树

解题思路:

  • 当我们面对累加二叉搜索树的问题时,可能会感到困惑,因为直观上它看起来比操作数组要复杂。
  • 使得每个节点 node 的新值等于原树中大于或等于 node.val 的值之和
  • 但一旦我们认识到二叉搜索树的有序性,问题就变得简单了。就像处理一个有序数组[2, 5, 13],我们可以从后向前进行累加,得到新的数组[20, 18, 13]。
  • 这种遍历方式在数组中很常见,而在二叉搜索树中,我们只需要调整遍历的顺序,采用反中序遍历(即先遍历右子树,然后是根节点,最后是左子树),就可以实现同样的顺序累加。这样一来,原本看似复杂的累加操作,就变成了一个简单的遍历和累加过程

递归法

pre指针的使用技巧: 本题依然需要一个pre指针记录当前遍历节点cur的前一个节点,这样才方便做累加。

递归三部曲:

  1. 确定递归函数的返回值和参数

    nt pre = 0; // 记录前一个节点的数值
    void traversal(TreeNode* cur)
    
  2. 确定递归函数的终止条件

    if (cur == NULL) return;
    
  3. 确定单层循环逻辑

    注意要右中左来遍历二叉树, 中节点的处理逻辑就是让cur的数值加上前一个节点的数值。

    traversal(cur->right);  // 右
    cur->val += pre;        // 中
    pre = cur->val;
    traversal(cur->left);   // 左
    

完整代码如下:

class Solution {
private:int pre = 0; // 记录前一个节点的数值void traversal(TreeNode* cur) { // 右中左遍历if (cur == NULL) return;traversal(cur->right);cur->val += pre;pre = cur->val;traversal(cur->left);}
public:TreeNode* convertBST(TreeNode* root) {pre = 0;traversal(root);return root;}
};

迭代法

迭代法其实就是中序模板题了,确定一个自己习惯的写法。

class Solution {
private:int pre; // 记录前一个节点的数值void traversal(TreeNode* root) {stack<TreeNode*> st;TreeNode* cur = root;while (cur != NULL || !st.empty()) {if (cur != NULL) {st.push(cur);cur = cur->right;   // 右} else {cur = st.top();     // 中st.pop();cur->val += pre;pre = cur->val;cur = cur->left;    // 左}}}
public:TreeNode* convertBST(TreeNode* root) {pre = 0;traversal(root);return root;}
};

二叉树总结篇

二叉树的理论基础

二叉树的种类、存储方式、遍历方式、定义方式

二叉树的遍历方式

  • 深度优先遍历
  • 广度优先遍历

求二叉树的属性

二叉树的改造与修改

求二叉搜索树的属性

二叉树公共祖先问题

二叉搜索树的修改与改造

小结:

note:二叉树的遍历顺序的选择

  • 如果是要构造二叉树,无论是普通的二叉树还是二叉搜索树,通常都是先处理根节点,也就是前序遍历。
  • 当我们想要计算普通二叉树的一些属性时,后序遍历是个不错的选择,因为这样可以在访问节点之前先得到其左右子树的信息,通常需要通过递归函数的返回值来进行计算。
  • 而对于二叉搜索树,由于其元素是有序的,中序遍历是最佳选择,因为这样可以直接利用树的有序性,比如进行排序或查找操作。

​ 注意在普通二叉树的属性中,用的是一般为后序,例如单纯求深度就用前序,二叉树:找所有路径 (opens new window)也用了前序,这是为了方便让父节点指向子节点

所以求普通二叉树的属性还是要具体问题具体分析,才能让问题变得简洁。


总结

学到了那些东西:

  • 二叉树的构造(前序构造),二叉树的遍历方式(前中后)
  • 递归和迭代,一般递归的思路来的比较简单,代码也是比较简洁。递归三部曲(1.2.3)。
  • pre指针的使用,这是一个技巧。
  • 看到二叉搜索树,一定要记得利用他的特性,有序。(在本节,迭代的代码也是比较简单的。)

关于二叉树的章节,今天是完结篇,整体下来,学的有些稀里糊涂,大概过了一边,顺了一遍思路。很多题目自己为了节省时间,还有偷懒,就没有自己亲手去敲的,不知道是因为自己太懒还是太烂,总有畏难情绪,觉得自己敲了也敲不对,敲了也没用只是浪费时间,就有些投机取巧,没有去敲。这样下来,总感觉收获很少,但哪位老板能和我说一下,你们是怎么坚持,每题都敲代码的吗?(这对我很重要)

​ 总之,二叉树,这一个章节也是结束了,马上要开始一个新的章节回溯,杜绝懒惰,从我做起,加油!!

相关文章:

Day 21代码|随想录| 二叉树完结撒花,今日刷题669.修剪二叉搜索树、108.将有序数组转换为二叉搜索树、538.吧二叉搜索树转换为累加树

提示&#xff1a;DDU&#xff0c;供自己复习使用。欢迎大家前来讨论~ 文章目录 二叉树 Part06二、题目题目一&#xff1a;669.修剪二叉搜索树解题思路&#xff1a;递归法迭代法&#xff1a; 题目二&#xff1a; 108.将有序数组转换为二叉搜索树解题思路递归法&#xff1a;迭代…...

cmake教程一

1. Start 1.1 构建简单工程 cmake_minimum_required(VERSION 3.0) project(Step1) add_executable(Step1 main.cpp)设置cmake最低版本要求设置工程名字设置工程生成可执行程序 2. 声明 C Standard set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED True)如果我…...

3D场景标注标签信息,three.js CSS 2D渲染器CSS2DRenderer、CSS 3D渲染器CSS3DRenderer(结合react)

如果你想用HTML元素作为标签标注三维场景中模型信息&#xff0c;需要考虑定位的问题。比如一个模型&#xff0c;在代码中你可以知道它的局部坐标或世界坐标xyz&#xff0c;但是你并不知道渲染后在canvas画布上位置&#xff0c;距离web页面顶部top和左侧的像素px值。自己写代码把…...

C++参悟-单例模式

单例模式 一、概述1. 特点2. 实现方式3. 应用场景 二、实现代码1. 静态局部变量的懒汉单例2. 加锁的懒汉式单例3. 使用 C11 中的 std::call_one 的懒汉单例4. 饿汉式单例 一、概述 这里记录一下单例模式的最常用使用&#xff0c;单例模式&#xff08;Single Pattern&#xff0…...

【题解】—— LeetCode一周小结32

&#x1f31f;欢迎来到 我的博客 —— 探索技术的无限可能&#xff01; &#x1f31f;博客的简介&#xff08;文章目录&#xff09; 【题解】—— 每日一道题目栏 上接&#xff1a;【题解】—— LeetCode一周小结31 5.不含连续1的非负整数 题目链接&#xff1a;600. 不含连续…...

详解线索分层的目的、维度与创新实践

线索分层是一个系统性的过程&#xff0c;旨在更有效地管理、跟踪和利用线索资源。这一过程可以借鉴多种策略和方法&#xff0c;特别是在用户运营和市场营销中。 1、线索分层的目的 线索分层的主要目的是根据线索的不同特征或成熟度&#xff0c;将其分类管理&#xff0c;以便更…...

于8月21号的回顾

傍晚的日落和逐渐深邃的夜&#xff0c;驱散了白天的极致闷热。倦怠和疲惫充斥着大脑&#xff0c;喧嚣的浮沉又在耳边轰鸣。 我不曾想到&#xff0c;再次打开博客已经是两年后的今天了。手指轻轻滑过鼠标&#xff0c;博客的页面缓缓加载&#xff0c;那些被时间尘封的记忆瞬间涌…...

Abstract Class抽象类

抽象类&#xff08;Abstract Class&#xff09;在面向对象编程中是一种特殊的类&#xff0c;它不能被实例化&#xff0c;即不能创建该类的对象。抽象类主要用于定义一组接口&#xff08;即方法&#xff09;&#xff0c;这些方法的具体实现由子类来完成。抽象类通常用于表示一种…...

webrtc ns 降噪之粉红噪声参数推导

webrtc中降噪中&#xff0c;前50帧需要进行简单噪声估计&#xff0c;使用白噪声和粉红噪声模型估算。 首先我们 复习 有色噪声&#xff08;包含白噪声&#xff09;的一般模型&#xff1a; S(f) 是频率 f 处的功率谱密度。f是频率。α 是一个频谱指数&#xff0c;通常在1左右。…...

IO进程线程8月21日

1&#xff0c;思维导图 2&#xff0c;登录 #ifndef __LOG_H__ #define __LOG_H__ #include<myhead.h> typedef struct {char name[20];char pwd[20]; }str;int regist();int login(); #endif#include"log.h" int login() {char a[20]"\n";str p,s;…...

Web安全:SqlMap工具

一、简介 sqlmap 是一款开源的渗透测试工具&#xff0c;可以自动化进行SQL注入的检测、利用&#xff0c;并能接管数据库服务器。它具有功能强大的检测引擎,为渗透测试人员提供了许多专业的功能并且可以进行组合&#xff0c;其中包括数据库指纹识别、数据读取和访问底层文件系统…...

用手机写一本电子书

第1步、进入Andi.cn网站 第2步、点击登录&#xff0c;注册用户 第3步、点击去创作&#xff0c;进入创作页面 第4步、点击右下角的小笔&#xff0c;写一篇文章 第5步、下翻&#xff0c;点击提交按钮 第6步、再写一篇文章 第7步、点击栏目设计 第8步、进入栏目设计&#xff0c;点…...

【网络编程】基于UDP的TFTP文件传输

1&#xff09;tftp协议概述 简单文件传输协议&#xff0c;适用于在网络上进行文件传输的一套标准协议&#xff0c;使用UDP传输 特点&#xff1a; 是应用层协议 基于UDP协议实现 数据传输模式 octet&#xff1a;二进制模式&#xff08;常用&#xff09; mail&#xff1a;已经不再…...

Vue 3 + Pinia 实现网页刷新功能

概述 在现代 Web 开发中&#xff0c;保持用户界面的动态性和响应性至关重要。当用户触发某些操作时&#xff0c;例如点击按钮或者完成表单提交&#xff0c;我们往往需要刷新页面的一部分来展示最新的数据。本文将介绍如何使用 Vue 3 和 Pinia 来实现这一功能。 技术栈 Vue 3…...

DVWA综合靶场漏洞讲解

目录 综合靶场漏洞讲解 Brute Force Low Medium High Command Injection Low Medium High File Inclusion Low,Medium,High File Upload Low Medium High SQL Injection Low Medium High SQL Injection (Blind) Low Medium High XSS&#xff08;DOM&am…...

实现Bezier样条曲线

1.给出n1 个控制点pk(xk,yk,zk),这里k可取值0-n,多项式函数公式如下 获取的单个点的代码 void zmBezier::getPoint(float u, double p[3]) {int n m_count - 1;double x 0, y 0, z 0;for(int k 0; k < n; k){x m_ctrlPoints[k][0] * BEZ_k_n(n, k, u);y m_ctrlPoin…...

MySQL中的EXPLAIN的详解

一、介绍 官网介绍&#xff1a; https://dev.mysql.com/doc/refman/5.7/en/explain-output.htmlhttps://dev.mysql.com/doc/refman/8.0/en/explain-output.htmlexplain&#xff08;执行计划&#xff09;&#xff0c;使用explain关键字可以模拟优化器执行sql查询语句&#xff…...

LearnOpenGL——SSAO学习笔记

LearnOpenGL——SSAO学习笔记 SSAO一、基本概念二、样本缓冲三、法向半球四、随机核心转动五、SSAO着色器六、环境遮蔽模糊七、应用SSAO遮蔽因子 SSAO 一、基本概念 环境光照是我们加入场景总体光照中的一个固定光照常量&#xff0c;它被用来模拟光的散射(Scattering)。散射应…...

[C语言]-基础知识点梳理-文件管理

前言 各位师傅们好&#xff0c;我是qmx_07&#xff0c;今天给大家讲解文件管理的相关知识&#xff0c;也就是常见的 读取&#xff0c;删除一类的操作 文件 为什么要使用文件&#xff1f; 程序的数据是存储在电脑的内存中&#xff0c;如果程序退出&#xff0c;内存回收&…...

pcdn闲置带宽被动收入必看教程。第五讲:光猫更换和基础设置

PCDN闲置带宽被动收入必看教程 —— 第五讲&#xff1a;光猫更换和基础设置 为了从闲置带宽中获得被动收入&#xff0c;高效的网络设备至关重要。运营商提供的光猫通常能满足日常家用需求&#xff0c;但对于PCDN应用来说&#xff0c;它们可能不足以提供所需的高性能和稳定性。…...

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...

ssc377d修改flash分区大小

1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程&#xff1a;如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket&#xff08;服务端和客户端都要&#xff09;2. 绑定本地地址和端口&#x…...

08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险

C#入门系列【类的基本概念】&#xff1a;开启编程世界的奇妙冒险 嘿&#xff0c;各位编程小白探险家&#xff01;欢迎来到 C# 的奇幻大陆&#xff01;今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类&#xff01;别害怕&#xff0c;跟着我&#xff0c;保准让你轻松搞…...

DAY 26 函数专题1

函数定义与参数知识点回顾&#xff1a;1. 函数的定义2. 变量作用域&#xff1a;局部变量和全局变量3. 函数的参数类型&#xff1a;位置参数、默认参数、不定参数4. 传递参数的手段&#xff1a;关键词参数5 题目1&#xff1a;计算圆的面积 任务&#xff1a; 编写一…...

麒麟系统使用-进行.NET开发

文章目录 前言一、搭建dotnet环境1.获取相关资源2.配置dotnet 二、使用dotnet三、其他说明总结 前言 麒麟系统的内核是基于linux的&#xff0c;如果需要进行.NET开发&#xff0c;则需要安装特定的应用。由于NET Framework 是仅适用于 Windows 版本的 .NET&#xff0c;所以要进…...

41道Django高频题整理(附答案背诵版)

解释一下 Django 和 Tornado 的关系&#xff1f; Django和Tornado都是Python的web框架&#xff0c;但它们的设计哲学和应用场景有所不同。 Django是一个高级的Python Web框架&#xff0c;鼓励快速开发和干净、实用的设计。它遵循MVC设计&#xff0c;并强调代码复用。Django有…...

基于Uniapp的HarmonyOS 5.0体育应用开发攻略

一、技术架构设计 1.混合开发框架选型 &#xff08;1&#xff09;使用Uniapp 3.8版本支持ArkTS编译 &#xff08;2&#xff09;通过uni-harmony插件调用原生能力 &#xff08;3&#xff09;分层架构设计&#xff1a; graph TDA[UI层] -->|Vue语法| B(Uniapp框架)B --&g…...