• 刷题LeetCode(Top 100-150题,至少刷两遍)。重点:链表、树、二分查找、动态规划、回溯、栈/队列。

  • 每一个题型,前10个高频题

算法思考框架参考:算法题思维框架-CSDN博客

高频顺序参考网站:CodeTop 面试题目总结

1.树

1.1102. 二叉树的层序遍历 - 力扣(LeetCode)https://leetcode.cn/problems/binary-tree-level-order-traversal/

思考:题目已经给出层序遍历,按照思考框架。

BFS:

 vector<vector<int>> levelOrder(TreeNode* root) {if(!root) return {};vector<vector<int>> ans;queue<TreeNode*> q;q.push(root);while(!q.empty()){int levelSize = q.size();vector<int> layer;for(int i = 0;i<levelSize;++i){auto node = q.front();q.pop();// process node->vallayer.push_back(node->val);if(node->left) q.push(node->left);if(node->right) q.push(node->right);}// current layer is overans.push_back(layer);}return ans;}

DFS:需要记录深度depth,回溯时根据depth添加到对应数组里。

class Solution {
public:vector<vector<int>> ans;void dfs(TreeNode* root,int depth){if(!root) return;if(depth>=ans.size()){ans.push_back({root->val});}else{ans[depth].push_back(root->val);}dfs(root->left,depth+1);dfs(root->right,depth+1);}vector<vector<int>> levelOrder(TreeNode* root) {if(!root) return {};dfs(root,0);return ans;}
};

1.2236. 二叉树的最近公共祖先 - 力扣(LeetCode)https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/

思考:按照思维框架,我们可以看出先需要知道左右子树,显然是后续遍历。

具体思路:

  1. 如果当前节点为nullptr,返回nullptr。
  2. 如果当前节点就是p或q,那么返回当前节点。
  3. 递归遍历左子树和右子树,得到左右子树的结果。
  4. 如果左子树和右子树的结果都不为空,说明当前节点就是p和q的最近公共祖先。
  5. 如果左子树结果不为空,右子树结果为空,说明p和q都在左子树中,返回左子树的结果。
  6. 如果右子树结果不为空,左子树结果为空,说明p和q都在右子树中,返回右子树的结果。
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {if(root == nullptr || root == p || root == q){return root;}TreeNode* left = lowestCommonAncestor(root->left,p,q);TreeNode* right = lowestCommonAncestor(root->right,p,q);if(left!=nullptr && right!=nullptr){return root;}return left!=nullptr?left:right;}

时间复杂度:O(N),最坏情况下,我们需要访问所有节点。

空间复杂度:O(H),递归调用的栈深度取决于二叉树的高度,最坏情况下(树退化为链表)为 O(N),平均情况下为 O(logN)。

1.3103. 二叉树的锯齿形层序遍历 - 力扣(LeetCode)https://leetcode.cn/problems/binary-tree-zigzag-level-order-traversal/description/

这道题BFS的变种,核心思路仍然仍按层遍历,但需要根据层数的奇偶性来决定遍历方向:

  1. 使用队列进行BFS:标准的层序遍历方法

  2. 使用标志位记录方向:用一个布尔值 leftToRight 记录当前层应该是从左到右还是从右到左

  3. 根据方向处理每层结果

    • 如果是左到右:直接按遍历顺序加入结果

    • 如果是右到左:将当前层的结果反转后加入结果

方法一:标准BFS + 反转

vector<vector<int>> zigzagLevelOrder(TreeNode* root) {if(!root) return {};vector<vector<int>> res;queue<TreeNode*> q;q.push(root);bool leftToRight = true;while(!q.empty()){int levelSize = q.size();vector<int> layer(levelSize);for(int i = 0;i<levelSize;++i){auto node = q.front();q.pop();int index = leftToRight?i:levelSize-1-i;layer[index] = node->val;if(node->left) q.push(node->left);if(node->right) q.push(node->right);}res.push_back(layer);leftToRight = !leftToRight;}return res;}
  • 时间复杂度:O(n)

  • 空间复杂度:O(n)

方法二:使用双端队列(Deque)

这种方法更高效,避免了反转操作:

class Solution {
public:vector<vector<int>> zigzagLevelOrder(TreeNode* root) {vector<vector<int>> result;if (!root) return result;deque<TreeNode*> dq;dq.push_back(root);bool leftToRight = true;while (!dq.empty()) {int levelSize = dq.size();vector<int> currentLevel;for (int i = 0; i < levelSize; i++) {if (leftToRight) {// 从左到右:从前面取,往后面加(先左后右)TreeNode* node = dq.front();dq.pop_front();currentLevel.push_back(node->val);if (node->left) dq.push_back(node->left);if (node->right) dq.push_back(node->right);} else {// 从右到左:从后面取,往前面加(先右后左)TreeNode* node = dq.back();dq.pop_back();currentLevel.push_back(node->val);if (node->right) dq.push_front(node->right);if (node->left) dq.push_front(node->left);}}result.push_back(currentLevel);leftToRight = !leftToRight;}return result;}
};

 方法三:DFS递归解法

class Solution {
public:vector<vector<int>> zigzagLevelOrder(TreeNode* root) {vector<vector<int>> result;dfs(root, 0, result);return result;}void dfs(TreeNode* node, int level, vector<vector<int>>& result) {if (!node) return;if (level >= result.size()) {result.push_back({});}if (level % 2 == 0) {// 偶数层:从左到右result[level].push_back(node->val);} else {// 奇数层:从右到左,插入到开头result[level].insert(result[level].begin(), node->val);}dfs(node->left, level + 1, result);dfs(node->right, level + 1, result);}
};

时间复杂度:O(N),每个节点被访问一次
空间复杂度:O(N),队列或递归栈的空间

1.4124. 二叉树中的最大路径和 - 力扣(LeetCode)https://leetcode.cn/problems/binary-tree-maximum-path-sum/

思路:

采用后序遍历的递归方法:

  1. 递归函数定义maxGain(TreeNode* node) 返回以该节点为起点的最大路径和(只能向下走)

  2. 计算当前节点的贡献值

    • 左子树的贡献:leftGain = max(maxGain(node->left), 0)

    • 右子树的贡献:rightGain = max(maxGain(node->right), 0)

  3. 更新全局最大值node->val + leftGain + rightGain

  4. 返回当前节点的最大贡献node->val + max(leftGain, rightGain)

class Solution {
private:int maxSum = INT_MIN;public:int maxPathSum(TreeNode* root) {maxGain(root);return maxSum;}int maxGain(TreeNode* node) {if (!node) return 0;// 递归计算左右子树的最大贡献值,如果为负则取0(相当于不选择)int leftGain = max(maxGain(node->left), 0);int rightGain = max(maxGain(node->right), 0);// 当前节点作为转折点的路径和int priceNewPath = node->val + leftGain + rightGain;// 更新全局最大值maxSum = max(maxSum, priceNewPath);// 返回当前节点的最大贡献(只能选择一边)return node->val + max(leftGain, rightGain);}
};
  • 时间复杂度:O(N),每个节点访问一次

  • 空间复杂度:O(H),递归栈的深度,H为树的高度

1.5

199. 二叉树的右视图 - 力扣(LeetCode)https://leetcode.cn/problems/binary-tree-right-side-view/思路:

这道题要求从右侧观察二叉树时能看到的节点,实际上就是求每一层最右边的节点

主要有两种方法:

  1. BFS层序遍历:记录每层的最后一个节点

  2. DFS递归:按照根→右→左的顺序遍历,记录每层第一个访问到的节点

方法一:BFS层序遍历(推荐)

ector<int> rightSideView(TreeNode* root) {vector<int> result;if (!root) return result;queue<TreeNode*> q;q.push(root);while (!q.empty()) {int levelSize = q.size();for (int i = 0; i < levelSize; i++) {TreeNode* node = q.front();q.pop();// 如果是当前层的最后一个节点,加入结果if (i == levelSize - 1) {result.push_back(node->val);}if (node->left) q.push(node->left);if (node->right) q.push(node->right);}}return result;}

方法二:DFS递归

思路:按照根→右→左的顺序遍历,每层第一个访问到的节点就是右视图能看到的节点。

class Solution {
public:vector<int> rightSideView(TreeNode* root) {vector<int> result;dfs(root, 0, result);return result;}void dfs(TreeNode* node, int depth, vector<int>& result) {if (!node) return;// 如果当前深度等于结果数组大小,说明是这一层第一个访问的节点(最右边)if (depth == result.size()) {result.push_back(node->val);}// 先递归右子树,再递归左子树dfs(node->right, depth + 1, result);dfs(node->left, depth + 1, result);}
};
  • 时间复杂度:O(N),每个节点访问一次

  • 空间复杂度

    • BFS:O(W),W为树的最大宽度

    • DFS:O(H),H为树的高度(递归栈深度)

1.694. 二叉树的中序遍历 - 力扣(LeetCode)https://leetcode.cn/problems/binary-tree-inorder-traversal/

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

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

相关文章

服务器安装 LDOPE(MODIS 数据处理工具)

目录下载方式1-&#xff08;简单快捷&#xff09;根据WRF-VPRM 需要打补丁下载方式2&#xff1a;&#xff08;手动安装依赖&#xff09;一、安装所需依赖库&#xff08;4 个主库 2 个基础库&#xff09;另- HDF-EOS 手动编译二、解压并安装 LDOPE参考下载方式1-&#xff08;简…

克隆代币 + 捆绑开盘:多链环境下的低成本发币玩法

在加密世界&#xff0c;发币已经不再是“少数开发者的专利”。随着工具的普及&#xff0c;任何人都可以快速发行一个在加密世界&#xff0c;发币已经不再是“少数开发者的专利”。随着工具的普及&#xff0c;任何人都可以快速发行一个代币。但问题是&#xff1a;如何在保证低成…

数据结构中的 二叉树

1.前言 在 Java 中&#xff0c;树&#xff08;Tree&#xff09;是一种非线性数据结构&#xff0c;由节点&#xff08;Node&#xff09;组成&#xff0c;常见的线性表则是我们之前学过的顺序表、链表、栈、队列等等。每个节点包含数据和指向子节点的引用。树的常见实现方式包括二…

IntelliJ IDEA 启动项目时配置端口指南

&#x1f31f; 一、为什么需要手动设置启动端口&#xff1f; 默认情况下&#xff0c;Spring Boot 应用会使用 8080 端口启动。但在以下场景中&#xff0c;我们必须自定义端口&#xff1a; 多个微服务同时运行&#xff0c;需避免端口冲突&#xff1b;团队协作开发&#xff0c;统…

spark sql之from_json函数

目录前言函数语法参数说明返回值案例案例1案例2前言 在Spark SQL中&#xff0c;from_json函数用于解析包含JSON字符串的列&#xff0c;并将其转换为Spark SQL的结构化类型&#xff08;如struct、map或array&#xff09; 函数语法 from_json(jsonStr, schema [, options])参数…

数据结构 之 【位图的简介】

目录 1.位图的引入 2.位图概念 3.位图的实现 3.1前提准备 3.2set 3.3reset 3.4test 4.位图的应用 1.位图的引入 给40亿个不重复的无符号整数&#xff0c;没排过序 再给一个无符号整数&#xff0c;如何快速判断这个无符号整数是否在 这40亿个数中 首先&#xff0c;一个…

[iOS] ViewController 的生命周期

文章目录前言一、UIViewController 生命周期有关函数二、UIViewController 中函数的执行顺序运行结果1.present和dismiss2.push和pop三、总结前言 UIViewController 是在 iOS 开发中一个非常重要的角色&#xff0c;他是 view 和 model 的桥梁&#xff0c;通过 UIViewControlle…

第30章 零售与电商AI应用

本章将深入探讨人工智能在零售与电商领域的革命性应用。我们将从智能推荐系统、动态定价、库存管理到创新的虚拟试衣间&#xff0c;全面解析AI如何重塑购物体验和商业运营效率&#xff0c;并为每个关键技术点提供代码实战&#xff0c;帮助你掌握将AI应用于真实商业场景的能力。…

QT通过QModbusRtuSerialMaster读写电子秤数据实例

一、电子称常用功能&#xff1a;称重、清零、去皮&#xff1b;电子秤的通讯方式&#xff1a;Modbus通信、串口通信。二、QT读写电子秤软件界面如下&#xff1a;三、核心代码如下&#xff1a;.pro项目文件代码&#xff1a;QT core gui serialbus serialport.h头文件代码#…

sqlmap常用命令

ZZHow(ZZHow1024) 一、扫描注入点 1.GET方法&#xff0c;给URL&#xff1a; #探测该url是否存在漏洞 python sqlmap.py -u "http://192.168.10.1/sqli/Less-1/?id1"#如果我们已经知道admin这里是注入点的话&#xff0c;可以在其后面加个*来让sqlmap对其注入 python …

JVM如何排查OOM

当JVM&#xff08;Java虚拟机&#xff09;出现OOM&#xff08;OutOfMemoryError&#xff09;时&#xff0c;可以按照以下步骤和方法&#xff0c;用于帮助定位和解决JVM中的OOM问题1.查看异常堆栈信息查看异常堆栈信息&#xff08;StackTrace&#xff09;是定位问题的关键。OOM异…

存算一体芯片生态评估:从三星PIM到知存科技WTM2101

点击 “AladdinEdu&#xff0c;同学们用得起的【H卡】算力平台”&#xff0c;注册即送-H卡级别算力&#xff0c;80G大显存&#xff0c;按量计费&#xff0c;灵活弹性&#xff0c;顶级配置&#xff0c;学生更享专属优惠。 引言&#xff1a;存算一体技术的崛起与意义 在传统冯诺…

[数据结构] 栈 · Stack

一.栈 stack 1.概念 栈 : 一种特殊的线性表 , 其只允许再固定的一段进行插入和删除元素操作 进行数据插入和删除操作的一段称为 栈顶 ; 另一端称为栈底栈中的数据元素遵循 先进后出 原则(LIFO)压栈 : 栈的插入操作叫做 进栈 或 压栈 或 入栈 , 入数据在栈顶出栈 : 栈的删除…

MySQL执行过程中如何选择最佳的执行路径

本篇文章介绍一个非常核心的数据库问题。MySQL 选择最佳执行路径&#xff08;即“查询优化”&#xff09;的过程是由其查询优化器&#xff08;Query Optimizer&#xff09; 完成的。 简单来说&#xff0c;优化器的目标是&#xff1a;在多种可能的执行方案中&#xff0c;选择一个…

【设计模式】从游戏角度开始了解设计模式 --- 抽象工厂模式

永远记住&#xff0c;你的存在是有意义的&#xff0c; 你很重要&#xff0c; 你是被爱着的&#xff0c; 而且你为这个世界带来了无可取代的东西。 -- 麦克西 《男孩、鼹鼠、狐狸和马》-- 从零开始了解设计模式抽象工厂模式抽象工厂模式 今天我们一起来探究抽象工厂模式&#x…

tensorflow.js 使用场景

TensorFlow.js (简称 TF.js) 是一个利用 WebGL 和 Node.js 在浏览器和服务器端进行机器学习模型训练和部署(推理)的 JavaScript 库。它的核心价值在于将机器学习的能力带入了 Web 开发者和 JavaScript 生态的领域。 其主要应用场景可以分为以下几大类: 一、在浏览器中直接进…

详解mcp以及agen架构设计与实现

文章目录1.MCP概念2.MCP服务端主要能力3.MCP技术生态4.MCP与Function call区别5.MCP生命周期6.MCP java SDK7.MCP应用场景8.基于springAIollma阿里qianwenmcp设计私有AIAgent应用实现9.AI java项目落地技术选型10.构建AI Agent四大模块11.LLM(大模型)与MCP之间关系12.A2A、MCP、…

六级第一关——下楼梯

上目录&#xff1a; 目录 题目描述 输入格式 输出格式 输入输出样例 说明/提示 一、DP的意义以及线性动规简介 在一个困难的嵌套决策链中&#xff0c;决策出最优解。 二、动态规划性质浅谈 三、子序列问题 &#xff08;一&#xff09;一个序列中的最长上升子序列&am…

【Linux基础】Linux系统配置IP详解:从入门到精通

目录 1 Linux网络配置概述 2 网卡配置文件位置和命名规则 2.1 配置文件位置 2.2 网卡命名规则 2.3 配置文件命名示例 3 网卡配置文件详解 3.1 主要参数说明 4 Linux系统配置IP步骤 4.1 DHCP动态配置 4.2 静态IP配置 5 Linux网络配置流程 5.1 网络配置流程 5.2 网卡…

C语言sprintf的高效替代方案

C语言的sprintf和snprintf将变量格式化输出到内存buffer&#xff0c;其功能强大&#xff0c;用起来很方便。但sprintf系列函数的运行效率低下&#xff0c;主要包括四方面的原因&#xff1a;格式字符串解析、变参处理、locale&#xff08;本地化&#xff09;支持和通用&#xff…