【大厂秋招高频算法】阿里秋招高频算法题汇总

欢迎关注公众号(通过文章导读关注:【11来了】),及时收到 AI 前沿项目工具及新技术的推送!

在我后台回复 「资料」 可领取编程高频电子书
在我后台回复「面试」可领取硬核面试笔记

文章导读地址:点击查看文章导读!

感谢你的关注!

阿里秋招高频算法题汇总!

image-20240314123527084

这里讲一下阿里秋招中的高频算法题,分为三个部分: 基础篇中级篇进阶篇

目的就是为了应对秋招中的算法题,其实过算法题的诀窍就在于 理解的基础上 + 背会

看到一个题目,首先要了解题目考察的算法是什么,这个算法要理解,至于具体实现的话,就靠背会了(多写、多练),没有什么捷径!

还有一点要注意的是,在大厂的比试中, 可能考察算法的方式是 ACM 模式 ,这一点和力扣上不同,ACM 模式需要我们自己去引入对应的包,以及自己写算法,力扣是将方法框架给定,只需要在方法内写代码就可以了,这一点要注意!

接下来开始阿里秋招算法的算法讲解,文章内的题目都在 LeetCode 上,因此这里只列出对应的题目序号、题目简介!

基础篇

在基础篇中考察算法更偏向于基础的数据结构,以及 dfs,包括:

  • 深度优先搜索:dfs
  • 队列
  • 动态规划:dp

LC 225. 用队列实现栈(简单)

这个考察就是基础数据结构是否会应用 ,题目要求:使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(pushtoppopempty

实现思路比较简单,队列是 先进先出 ,而栈是 先进后出 ,那么使用队列模拟栈的话,只要使用两个队列,使用【队列1】作为中转,添加的新元素先加入【队列1】,再将【队列2】的元素加入到【队列1】的后边,这样在【队列1】中添加的新元素就在第一个的位置,可以实现栈 最后加入的元素最先被弹出 的特性!

流程如下:

步骤1:先加入元素 A,【队列1】作为中转,因此元素 A 先加入【队列1】

image-20240313145630426

步骤2:再加入元素 B,将 B 先加入【队列1】,此时元素 B 是在第一个位置,再将【队列2】中的元素 A 加入到【队列1】,此时元素顺序就被反转了,符合栈 后入先出 的顺序

image-20240313145752490

可以看到,元素 A 先入队,在队列 2 弹出的时候,元素 A 是最后弹出的,和栈的特性一致,接下来看一下代码实现,注释已经放在代码中了:

class MyStack {Queue<Integer> q1;Queue<Integer> q2;public MyStack() {// 初始化两个队列q1 = new LinkedList<>();q2 = new LinkedList<>();}// 向栈中加入元素public void push(int x) {// 先加入到队列 1 中,队列 1 作为一个中转的作用q1.offer(x);// 将队列 2 的元素一个一个放入队列 1,这样在队列 1 中最后加入的元素其实是在第一个的位置,实现了栈的特性while (!q2.isEmpty()) {q1.offer(q2.poll());}// 交换两个队列Queue<Integer> tmp = new LinkedList<>();tmp = q1;q1 = q2;q2 = tmp;}public int pop() {// 弹出队列 2 的元素,并返回return q2.poll();}public int top() {// 返回队列 2 的队头元素,不弹出return q2.peek();}public boolean empty() {// 判空return q2.isEmpty();}
}/*** Your MyStack object will be instantiated and called as such:* MyStack obj = new MyStack();* obj.push(x);* int param_2 = obj.pop();* int param_3 = obj.top();* boolean param_4 = obj.empty();*/

LC 44. 通配符匹配(困难)

这个题目是进行字符串匹配,使用 动态规划 DP 来做

动态规划类的问题怎么学?

动态规划类的问题比较吃经验,做的题目如果少的话,看到新的题目一般都是做不出来的,所以对于动态规划类的问题,建议是把我们写过的题型给记住,知道他们的状态是如何转移的,这样就够了,毕竟我们是学习的,并不是发明创造算法的!

题目大致意思就是给定一个字符串 s 和字符模式 p,p 中有通配符 ?*

  • ? 匹配单个字符
  • * 匹配任意字符

答案输出 s 和 p 是否匹配

比如

s = "abc"
p = "a?c"
输出:true 表示 匹配
s = "abc"
p = "*"
输出:true 表示 匹配

首先定义动态规划数组 dp[n][m]dp[i][j] 表示 s 的前 i 个字符和 p 的前 j 个字符是否匹配

那么主要分为两种情况:

  • 第一种情况:p[j] != * ,如果 p[j] 不是 * 的话

    • p[j] == s[j] 或者 p[j] == ''?' ,此时 s[i]p[j] 是匹配的,那么此时 dp[i][j] 的状态由 dp[i-1][j-1] 转移过来
  • 第二种情况:p[j] == * ,这种情况比较复杂,因为我们并不清楚这个 * 到底可以匹配多少个字符,可能匹配 0 个、1个、… j 个字符,如下:

    • 如果匹配 0 个字符,dp[i][j] = dp[i][j-1]
    • 如果匹配 1 个字符,dp[i][j] = dp[i-1][j-1]
    • 如果匹配 2 个字符,dp[i][j] = dp[i-2][j-1]

    那么这样的话,计算 dp 的状态还需要再次遍历一下 i,时间复杂度比较高,因此这里简化一下

    dp[i-1][j] 的状态其实是由 dp[i-1][j-1]、dp[i-2][j-1]... 转移过来,那么这里可以发现 dp[i-1][j] 的状态就符合了上边匹配 1 个、2 个字符的情况,因此这里就不需要进行循环了,此时 dp[i][j] 的状态如下:

    • 如果匹配 0 个字符,dp[i][j] = dp[i][j-1]
    • 如果匹配 1 个、2 个…多个字符,dp[i][j] = dp[i-1][j]

    所以这里 dp 的状态转换简化为: dp[i][j] = dp[i][j-1] && dp[i-1][j]

综上,DP 状态转移主要分为两个状态:

  • p[j] != '*' 时,dp[i][j] = dp[i-1][j-1]
  • p[j] == '*' 时,dp[i][j] = dp[i][j-1] && dp[i-1][j]
class Solution {public boolean isMatch(String s, String p) {int n = s.length();int m = p.length();s = " " + s;p = " " + p;char[] s1 = s.toCharArray();char[] p1 = p.toCharArray();boolean[][] dp = new boolean[n+1][m+1];// 状态初始化,这个状态影响着后边的状态,所以需要初始化一下dp[0][0] = true;// i 从 0 开始遍历,因为 dp[0][j] 表示如果 s 串为空串,p 是否匹配 s,这其实是有可能会匹配的,如果 p 全是 * 的话,会匹配// 因此 i 从 0 开始遍历,需要对 dp[0][j] 的状态进行设置for (int i = 0; i <= n; i ++) {for (int j = 1; j <= m; j ++) {if (i > 0 && (s1[i] == p1[j] || p1[j] == '?')) {// 如果字符相等,或者是 ? 通用匹配符的话,dp[i][j] 的状态从 dp[i-1][j-1] 转移而来dp[i][j] = dp[i-1][j-1];} else if (p1[j] == '*') {// 这里表示 p[j] 为 * 匹配 0 个字符的情况dp[i][j] = dp[i][j-1];if (i > 0) {// dp[i-1][j] 表示 p[j] 为 * 匹配 1 个、2个...多个字符的情况dp[i][j] = dp[i][j] || dp[i-1][j];}}}}return dp[n][m];}
}

LC 78. 子集(中等)

这道题是给定一个数组,让你返回所有的子数组,示例输入输出如下:

输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]

可以看到,就是通过不同的排列组合,将所有可能的情况给查出来就好了

这里使用 二进制枚举 来做,对于 nums 数组种的每一位都可能取或者不取,这样就可以枚举出来所有的子数组了,二进制枚举也是比较常用的算法

这里画图举个例子:

image-20240313170822841

可以看到,只需要 枚举所有的二进制 就可以枚举出来所有的子数组了

这里怎么枚举所有的二进制呢?

比如说 nums 数组长度为 3,那么只需要从 0 遍历到 1 <<< 3 - 1 也就是从 0 遍历到 7,这样就可以将所有的二进制全部遍历出来了

代码如下:

class Solution {public List<List<Integer>> subsets(int[] nums) {List<List<Integer>> res = new ArrayList<>();int n = nums.length;// 枚举所有的二进制for (int i = 0; i < 1 << n; i++) {List<Integer> tmp = new ArrayList<>();// 遍历每一位for (int j = 0; j < n; j ++) {// 如果第 j 位是 1,表示子数组取这一位,加入到子数组 tmp 中去if ((i >> j & 1) == 1) {tmp.add(nums[j]);}}res.add(tmp);}return res;}
}

LC 145. 二叉树的后序遍历(简单)

二叉树的遍历其实还是比较容易考察的,这里写两版代码:

  • dfs 解决:使用 dfs 解决的话,比较方便
  • 迭代解决:迭代解决的话,需要我们手动记录上次访问的节点,来手动实现回溯,因此稍微麻烦一些

后序遍历的话就是先遍历左子树,再遍历右子树,最后遍历根节点,也就是 LRN

dfs 实现
class Solution {List<Integer> res = new ArrayList<>();public List<Integer> postorderTraversal(TreeNode root) {dfs(root);return res;}void dfs(TreeNode root) {// 如果到空节点了,就不接着往下走了,返回if (root == null) return;// 先遍历左子树dfs(root.left);// 再遍历右子树dfs(root.right);// 最后是根节点res.add(root.val);}
}
迭代实现

迭代实现的话,需要我们手动记录上一次节点,来实现回溯

首先要使用栈来记录我们遍历的节点,这里使用链表来模拟栈

之后一直向左子树遍历,当没有左子树之后,就向右子树遍历,在右子树中也还是先向左子树遍历再向右子树遍历

这里定义了 last 节点 来记录回溯的上一个节点,避免回溯之后,由继续向下遍历,导致死循环

这里为了回溯,使用了栈,将元素都推入栈中,当遍历到最底层之后,再从栈中取出元素进行回溯即可!

代码的话,实现的比较精妙(如果有不理解的地方,直接背了就好了,因为这类题型其实是比较固定的),看着流程,自己模拟画图一下就好了, 注意在理解的基础上,可以自己手敲个 3-5 遍,提升一下印象!

class Solution {public List<Integer> postorderTraversal(TreeNode root) {// 这里使用链表来模拟栈了LinkedList<TreeNode> s = new LinkedList<>();TreeNode now = root;TreeNode last = null;List<Integer> res = new ArrayList<>();// 如果当前节点为空,并且栈中没有元素了,说明所有元素都遍历完毕了while (now != null || !s.isEmpty()) {// 如果当前节点不是空,就都压入到栈中if (now != null) {s.addFirst(now);now = now.left;} else {now = s.getFirst();// 如果还有右子树,就往右子树遍历// last != now.right 表示可能刚刚才从右子树遍历完回到当前节点,既然回溯了,如果继续向右子树遍历,就反复横跳,死循环了if (now.right != null && last != now.right) {now = now.right;} else {// 到了这个 if 分支,说明右子树已经为空,或者已经遍历过右子树了// 于是将当前节点加入数组now = s.removeFirst();res.add(now.val);last = now;// 这里将 now 定义为 null,避免重入压入到栈中now = null;}}}return res;}
}

LC 268. 丢失的数字(简单)

这个题目比较简单了,给定一个数组,长度为 n,找出来 [0, n] 范围内的数字,哪一个数字没有在数组中出现

这里题目给定的数据范围 n 最大为 104 ,所以直接声明一个长度为 n+1 的数组,如果出现过的数字标记为 true,再遍历一遍,标位为 fasle 的表明在数组中没有出现,如下图:

image-20240313175938868

代码如下:

class Solution {public int missingNumber(int[] nums) {int n = nums.length;// 标记数组 0-nboolean[] flag = new boolean[n + 1];for (int i = 0; i < n; i ++) {// 取出 nums[i] 的值,作为下标,在 flag 数组标记int idx = nums[i];flag[idx] = true;}for (int i = 0; i <= n; i ++) {// 如果标记为 false,说明这个下标没有在 nums 中出现,返回即可if (flag[i] == false) {return i;}}return -1;}
}

LC 344. 反转字符串(简单)

这道题也是简单题,对字符串反转

反转前:hello
反转后:olleh

不过这道题目有一点要求, 只能原地反转 ,不可以定义额外的数组进行操作,因此这里使用 递归 来做

定义一个递归函数 dfs(char[] s, int l, int r) 表示将 s[l]s[r] 进行互换,只要将两边的所有字符串都互换一下就可以了

代码如下:

class Solution {public void reverseString(char[] s) {int n = s.length;// 对 0 和 n-1 位置上的字符互换dfs(s, 0, n-1);}// dfs(s, i, j) 就是将 s[i] 和 s[j] 互换public void dfs(char[] s, int l, int r) {// 如果左指针 >= 右指针,就不需要反转了,退出递归就好if (l >= r) return;// 将 left 和 right 位置上的字符串互换进行反转char tmp = s[l];s[l] = s[r];s[r] = tmp;dfs(s, l + 1, r - 1);}
}

LC 350. 两个数组的交集 II(简单)

这道题目是返回两个数组的交集

给你两个整数数组 nums1nums2 ,请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。可以不考虑输出结果的顺序

输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2,2]

如下:

class Solution {public int[] intersect(int[] nums1, int[] nums2) {Map<Integer, Integer> map = new HashMap<>();int n = nums1.length;int m = nums2.length;for (int i = 0; i < n; i ++) {map.put(nums1[i], map.getOrDefault(nums1[i], 0) + 1);}// 记录交集的数的下标int k = 0; for (int i = 0; i < m; i ++) {// map 中记录了 nums1 中的所有数字出现的次数if (map.containsKey(nums2[i]) && map.get(nums2[i]) > 0) {nums1[k ++] = nums2[i];// 已经放入到交集数组中了,因此对 nums1 中出现的次数减 1map.put(nums2[i], map.get(nums2[i]) - 1);}}// 交集放在了 nums1 数组的 [0, k) 的位置上return Arrays.copyOfRange(nums1, 0, k);}
}

LC 557. 反转字符串中的单词 III(简单)

这道题目就是让反转字符串中的每一个单词:

输入:s = "Let's take LeetCode contest"
输出:"s'teL ekat edoCteeL tsetnoc"

像这一种反转类的题目都可以使用 来做,比如 hello ,按顺序压入栈为:hello,再一个个弹出顺序就反过来为:olleh

这里使用链表来模拟栈了,只操作一边就可以了

class Solution {public String reverseWords(String s) {StringBuilder res = new StringBuilder("");// 使用链表模拟栈LinkedList<Character> stack = new LinkedList<>();int i = 0, n = s.length();while (i < n) {while (i < n && s.charAt(i) != ' ') {stack.addFirst(s.charAt(i));i ++;}while(!stack.isEmpty()) {res.append(stack.removeFirst());}if (i < n) {res.append(" ");}i ++;}return res.toString();}
}

LC 617. 合并二叉树(简单)

给定两个二叉树,对两个二叉树进行合并,重叠的节点合并为两个节点相加的值,否则,合并为不为 null 的节点值,如下:

image-20240314121323181

使用 dfs 来做,两个树一起递归就可以了,分为三种情况:

  • 其中一个树为 null,返回不为 null 的节点
  • 两个节点都为 null,返回 null
  • 两个节点都不为 null,返回节点相加的值

这里前两种情况可以合并,如果有一个节点为 null,返回另一个节点就可以了,代码如下:

/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode() {}*     TreeNode(int val) { this.val = val; }*     TreeNode(int val, TreeNode left, TreeNode right) {*         this.val = val;*         this.left = left;*         this.right = right;*     }* }*/
class Solution {public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {// 递归,需要做空判断及时返回if (root1 == null) return root2;if (root2 == null) return root1;// 对两个节点合并TreeNode mergedNode = new TreeNode(root1.val + root2.val);// 对左子树合并mergedNode.left = mergeTrees(root1.left, root2.left);// 对右子树合并mergedNode.right = mergeTrees(root1.right, root2.right);return mergedNode;}
}

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

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

相关文章

Windows,MacOS,Linux下载python并配置环境图文讲解

Windows 打开python官网 点击download 点击黄色按钮 另存为 打开文件 全选 配置安装路径 安装中 关闭路径长度限制 完成 验证 同时按住winr(win就是空格键左边的东西) 输入cmd 键入python,如果出现版本(红框)即安装成功 MacOS 同理打开python官网 点击最新版本 拖…

看!Chat4.0如何看待AI与光纤资源管理软件的应用结合点及价值

问&#xff1a;你好&#xff0c;AI在光纤资源管理软件中有那些应用结合点&#xff0c;请详细描述应用结合点及价值? 答&#xff1a;AI在光纤资源管理软件中的应用结合点涉及多个方面&#xff0c;它们通过智能化的手段提高资源管理的效率和准确性。以下是一些关键的应用结合点及…

Midjourney视觉垫图

https://github.com/lllyasviel/Fooocus/discussions/117https://github.com/lllyasviel/Fooocus/discussions/117掌握Midjourney的垫图技巧&#xff1a;AI绘画中的参考利器本期将深入了解AI绘画的垫图技巧&#xff0c;让作品获得更好的出图效果https://mp.weixin.qq.com/s/RS2…

unity3d Animal Controller的Animal组件中Stances,Advanced基础部分理解

Stances 立场 立场要求在动物动画控制器上的姿态动画参数。 你可以有多个运动状态,并根据当前的立场使用它们 过渡的条件是: Stance StanceID Default Stance默认姿势 如果调用函数Stance_Reset&#xff08;&#xff09;&#xff0c;动物将返回到的默认姿势。 Current …

边缘计算网关的工作原理及其在工业领域的应用价值-天拓四方

随着物联网技术的快速发展&#xff0c;物联网时代已经悄然来临。在这个时代&#xff0c;数以亿计的设备相互连接&#xff0c;共享数据&#xff0c;共同构建智慧的世界。边缘计算网关通过将计算能力和数据存储推向网络的边缘&#xff0c;实现了对海量数据的实时处理&#xff0c;…

centos云服务器安装cs(cobaltstrike4.0)教程

1、先安装JAVA环境 mkdir download #创建download目录 cd download #进入download目录 mkdir java1.8 #在download目录下再创建java1.8目录 cd java1.8 #进入java1.8目录 wget https://repo.huaweicloud.com/java/jdk/8u201-b09/jdk-8u201-linux-x64.tar.gz #下载jdk压缩包 tar…

WordPress供求插件API文档:获取市场类型

请注意&#xff0c;该文档为&#xff1a; WordPress供求插件&#xff1a;一款专注于同城生活信息发布的插件-CSDN博客文章浏览阅读396次&#xff0c;点赞6次&#xff0c;收藏5次。WordPress供求插件&#xff1a;sliver-urban-life 是一款专注于提供同城生活信息发布与查看的插件…

vue生命周期函数原理解析,vue阻止事件冒泡方法实现

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

TransNeXt实战:使用TransNeXt实现图像分类任务(一)

文章目录 摘要安装包安装timm 数据增强Cutout和MixupEMA项目结构计算mean和std生成数据集 摘要 https://arxiv.org/pdf/2311.17132.pdf TransNeXt是一种视觉骨干网络&#xff0c;它集成了聚合注意力作为令牌混合器和卷积GLU作为通道混合器。通过图像分类、目标检测和分割任务…

Hive借助java反射解决User-agent编码乱码问题

一、需求背景 在截取到浏览器user-agent&#xff0c;并想保存入数据库中&#xff0c;经查询发现展示的为编码后的结果。 现需要经过url解码过程&#xff0c;将解码后的结果保存进数据库&#xff0c;那么有几种实现方式。 二、问题解决 1、百度&#xff1a;url在线解码工具 …

【gpt实践】比OpenAI 的 GPT-4 更好模型 Claude 3.0

Google 最近发布了最新的 Gemini 1.5 语言模型&#xff0c;震惊了世界。这是目前功能最强大的模型&#xff0c;拥有 100 万个上下文窗口&#xff0c;是所有大型基础模型中最大的。 OpenAI 的 GPT-4 才具有 128K 上下文窗口。 最近&#xff0c;谷歌最接近的竞争对手之一 Anthro…

记忆化搜索

记忆化搜索 怎么优化&#xff1f;这里为什么要用引用呢?记忆化搜索的含义记忆化搜索的框架1) 合法性剪枝2)偏序关系剪枝3)记忆化剪枝4)递归计算结果并返回 今天每日一题可以用dp做&#xff0c;但是看答案有人用记忆化搜索&#xff0c;以前也经常听到这个名词&#xff0c;so今天…

2024/3/14打卡棋子(14届蓝桥杯)——差分

标准差分模板 差分——前缀和的逆运算&#xff08;一维二维&#xff09;-CSDN博客 题目 小蓝拥有 nn 大小的棋盘&#xff0c;一开始棋盘上全都是白子。 小蓝进行了 m 次操作&#xff0c;每次操作会将棋盘上某个范围内的所有棋子的颜色取反(也就是白色棋子变为黑色&#xff0…

Android Button点击事件

一.Button点击事件 <!-- activity_main.xml --> <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android" xmlns:tools"http://schemas.android.com/tools"…

C++ //练习 10.34 使用reverse_iterator逆序打印一个vector。

C Primer&#xff08;第5版&#xff09; 练习 10.34 练习 10.34 使用reverse_iterator逆序打印一个vector。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09; 工具&#xff1a;vim 代码块 /**************************************************************…

Apollo:如何打造全球化的医疗AI,轻量级,重量级

Apollo&#xff1a;如何打造全球化的医疗AI&#xff0c;轻量级&#xff0c;重量级 提出背景将多种语言的医学数据混合使用时&#xff0c;这些数据是互相帮助&#xff08;互补&#xff09;还是互相冲突的&#xff1f;训练训练小型模型的初衷训练方法训练设置 效果代理调优&#…

Python实现一个简单的主机-路由器结构(计算机网络)

说明 本系统模拟实现了一个路由器与两个主机节点。该路由器将接收原始以太网帧&#xff0c;并像真正的路由器一样处理它们&#xff1a;将它们转发到正确的传出接口&#xff0c;处理以太网帧&#xff0c;处理 IPv4 分组&#xff0c;处理 ARP分组&#xff0c;处理 ICMP 分组&…

沉浸式感受旧时光,VR全景让游客都爱上老街区打卡地

近年来&#xff0c;随着城市建设的推进&#xff0c;很多老建筑以及周边的道路都发生了很大的变化&#xff0c;为了让更多的游客可以领略城市发展的进程以及旧时的人文风情&#xff0c;很多城市都会通过实地场景拍摄制作VR全景&#xff0c;将老街区、老建筑的真实场景进行虚拟再…

新型masked勒索病毒袭击工控行业

2019年10月9号总部设在荷兰海牙的欧洲刑警组织与国际刑警组织共同发布报告《2019互联网有组织犯罪威胁评估》&#xff0c;报告指出数据已成为网络犯罪分子的主机攻击目标&#xff0c;勒索软件仍是网络安全最大威胁&#xff0c;全球各界需要加强合作&#xff0c;联合打击网络犯罪…

【Vue3】路由的query参数和params参数

&#x1f497;&#x1f497;&#x1f497;欢迎来到我的博客&#xff0c;你将找到有关如何使用技术解决问题的文章&#xff0c;也会找到某个技术的学习路线。无论你是何种职业&#xff0c;我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章&#xff0c;也欢…