leetcode--二叉树
admin
2024-03-26 03:24:24
0

1.二叉树的递归遍历

写递归需要考虑

  1. 确定递归函数的参数和返回值: 确定哪些参数是递归的过程中需要处理的,那么就在递归函数里加上这个参数, 并且还要明确每次递归的返回值是什么进而确定递归函数的返回类型。

  2. 确定终止条件: 写完了递归算法, 运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构来保存每一层递归的信息,如果递归没有终止,操作系统的内存栈必然就会溢出。

  3. 确定单层递归的逻辑: 确定每一层递归需要处理的信息。在这里也就会重复调用自己来实现递归的过程。

前序遍历
void traversal(TreeNode* cur,vector& vec){  //①确定递归函数的参数和返回值if(cur == nullptr) return;  //②确定终止条件//③确定单层递归的逻辑vec.push_back(cur->val);traversal(cur->left,vec);traversal(cur->right,vec);}vector preorderTraversal(TreeNode* root) {vector result;traversal(root,result);return result;}

2.二叉树的非递归遍历

使用栈,对于前序遍历,先将根节点入栈,然后栈顶元素出栈,右节点入栈,左节点入栈。

vector preorderTraversal(TreeNode* root) {stack st;vector result;if(root == nullptr) return result;st.push(root);   //根节点入栈while(!st.empty()){TreeNode* node = st.top();st.pop();result.push_back(node->val);if(node->right) st.push(node->right);if(node->left) st.push(node->left);}return result;}

 后续遍历(左右中)可以根据前序遍历代(中左右)码修改得到。

前序遍历是中左右,因此我们可以得到中右左顺序的遍历方法,然后将中右左反转(reverse),得到左右中。

 vector postorderTraversal(TreeNode* root) {vector result;stack st;if(root == nullptr) return result;st.push(root);while(!st.empty()){TreeNode* cur = st.top();st.pop();result.push_back(cur->val);if(cur->left) st.push(cur->left);if(cur->right) st.push(cur->right);}reverse(result.begin(),result.end());return result;}

中序遍历的非递归和前序和后序不一样,需要遍历节点和处理节点两部分。

vector inorderTraversal(TreeNode* root) {vector result;stack st;TreeNode* cur = root;while(cur != nullptr || !st.empty()){   //循环条件是当前节点不为空,循环到最后当前节点是空的,为了让循环终止需要在加一个判断条件:判断栈是否为空,如果空跳出循环if(cur != nullptr){   //遍历节点st.push(cur);cur = cur->left;   //左}else{                 //处理节点cur = st.top();st.pop();result.push_back(cur->val);  //中cur = cur->right;}}return result;}

3.二叉树的层序遍历  (广度优先搜索)

vector> levelOrder(TreeNode* root) {vector> result;queue que;if(root == nullptr) return result;else{que.push(root);while(!que.empty()){int size = que.size();   //que.size是不断变化的vector vec;for(int i = 0; i < size; i++){TreeNode* cur = que.front();que.pop();vec.push_back(cur->val);if(cur->left) que.push(cur->left);if(cur->right) que.push(cur->right);}result.push_back(vec);}}return result;
}

二叉树的右视图

vector rightSideView(TreeNode* root) {queue que;if (root != NULL) que.push(root);vector result;while (!que.empty()) {int size = que.size();for (int i = 0; i < size; i++) {TreeNode* node = que.front();que.pop();if (i == 0) result.push_back(node->val);if (node->right) que.push(node->right);if (node->left) que.push(node->left);}}return result;}

4.翻转二叉树

(1)递归法

 TreeNode* invertTree(TreeNode* root) {//递归//1.确定递归函数的返回值和参数:返回头节点;参数需要当前节点//2.确定终止条件:当前节点为空的时候,就返回//3.单层递归的逻辑:交换左右孩子,然后以在孩子为根节点继续递归if(root == nullptr) return root;swap(root->left,root->right);invertTree(root->left); invertTree(root->right); return root;
}

(2)迭代法:深度优先遍历

TreeNode* invertTree(TreeNode* root) {//迭代法:深度优先遍历if(root == NULL) return root;stack st;st.push(root);while(!st.empty()){TreeNode* cur = st.top();st.pop();swap(cur->left,cur->right);if(cur->right) st.push(cur->right);if(cur->left) st.push(cur->left);}return root;}

(3)迭代法:广度优先遍历

TreeNode* invertTree(TreeNode* root) {//迭代法:广度优先遍历queue que;if(root == NULL) return root;que.push(root);while(!que.empty()){int size = que.size();for(int i = 0; i < size; i++){TreeNode* cur = que.front();que.pop();swap(cur->left,cur->right);if(cur->left) que.push(cur->left);if(cur->right) que.push(cur->right);}}return root;}

4.判断是否是对称树

迭代法

bool isSymmetric(TreeNode* root) {if(root == nullptr) return false;queue que;que.push(root->left);que.push(root->right);while(!que.empty()){  //没有判断空节点,这个队列一直都是非空,需要一个if跳出循环TreeNode* leftNode = que.front(); que.pop();TreeNode* rightNode = que.front(); que.pop();if(!leftNode && !rightNode) continue;if(!leftNode || !rightNode ||(leftNode->val != rightNode->val) ) return false;que.push(leftNode->left);que.push(rightNode->right);que.push(leftNode->right);que.push(rightNode->left);}return true;}

5.平衡二叉树

    每个节点左右两个子树的高度差的绝对值不超过 1 ,高度只能从下到上去查,所以只能后序遍历(左右中)

     //递归//1.函数返回值和参数:参数:当前传入节点。返回值:以当前传入节点为根节点的树的高度。//2.递归终止条件:当前节点为空//3.单层递归逻辑:求根节点左子树高度和其右子树高度的差值。分别求出其左右子树的高度,然后如果差值小于等于1,则返回当前二叉树的高度,否则则返回-1,表示已经不是二叉平衡树了。int getHeight(TreeNode* cur){if(cur == nullptr) return 0;int leftHeight = getHeight(cur->left);if(leftHeight == -1)  return -1;        // -1 表示已经不是平衡二叉树了,否则返回值是以该节点为根节点树的高度int rightHeight = getHeight(cur->right);if(rightHeight == -1) return -1;return abs(leftHeight - rightHeight) <= 1 ? 1 + max(leftHeight,rightHeight)  : -1 ;}bool isBalanced(TreeNode* root) {return getHeight(root) == -1 ? false : true; }

6.二叉树的所有路径

从根节点到叶子的路径,所以需要前序遍历,这样才方便让父节点指向孩子节点,找到对应的路径。

(1)递归法

 void traversal(TreeNode* cur,vector& result,string path){path = path + to_string(cur->val);if(cur->left) traversal(cur->left, result, path + "->");if(cur->right) traversal(cur->right, result, path + "->");if(cur->left == nullptr && cur->right == nullptr){ //叶子节点result.push_back(path);return;}}vector binaryTreePaths(TreeNode* root) {vector result;if(root == nullptr) return result;traversal(root,result,"");return result;}

(2)迭代法:使用栈

vector binaryTreePaths(TreeNode* root) {vector result;if(root == nullptr) return result;stack treeSt;  //存放树节点stack pathSt;     //存放路径treeSt.push(root);pathSt.push(to_string(root->val));while(!treeSt.empty()){TreeNode*  cur = treeSt.top(); treeSt.pop();string path = pathSt.top(); pathSt.pop();if(cur->right){treeSt.push(cur->right);pathSt.push(path + "->" + to_string(cur->right->val));}if(cur->left){treeSt.push(cur->left);pathSt.push(path + "->" + to_string(cur->left->val));}if(cur->left == nullptr && cur->right == nullptr){//叶子节点result.push_back(path);}}return result;}

相关题目:二叉树路径之和是否满足目标值

(方法一)

思路:根据上一题思路设置俩个栈,一个放节点值,一个放已经遍历节点之和

bool hasPathSum(TreeNode* root, int targetSum) {if(root == nullptr) return false;stack treeSt;stack sumSt;treeSt.push(root);sumSt.push(root->val);while(!treeSt.empty()){TreeNode* cur = treeSt.top();treeSt.pop();int curvalue = sumSt.top();sumSt.pop();if(cur->right){treeSt.push(cur->right);sumSt.push(curvalue + cur->right->val);}if(cur->left){treeSt.push(cur->left);sumSt.push(curvalue + cur->left->val);}if(cur->left == nullptr && cur->right == nullptr){//叶子节点if(curvalue == targetSum) return true;}}return false;}

(方法二)

此时栈里一个元素不仅要记录该节点指针,还要记录从头结点到该节点的路径数值总和,用pair结构来存放这个栈里的元素。定义为:pair pair<节点指针,路径数值>

bool hasPathSum(TreeNode* root, int targetSum) {if(root == nullptr) return false;stack> st;st.push(pair(root,root->val));while(!st.empty()){pair cur = st.top();st.pop();if(cur.first->right){st.push(pair(cur.first->right,cur.second + cur.first->right->val));}if(cur.first->left){st.push(pair(cur.first->left,cur.second + cur.first->left->val));}if(cur.first->left == nullptr && cur.first->right == nullptr){//叶子节点if(targetSum == cur.second) return true;}}return false;}

相关内容

热门资讯

linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
C++ 机房预约系统(六):学... 8、 学生模块 8.1 学生子菜单、登录和注销 实现步骤: 在Student.cpp的...
A.机器学习入门算法(三):基... 机器学习算法(三):K近邻(k-nearest neigh...
数字温湿度传感器DHT11模块... 模块实例https://blog.csdn.net/qq_38393591/article/deta...
有限元三角形单元的等效节点力 文章目录前言一、重新复习一下有限元三角形单元的理论1、三角形单元的形函数(Nÿ...
Redis 所有支持的数据结构... Redis 是一种开源的基于键值对存储的 NoSQL 数据库,支持多种数据结构。以下是...
win下pytorch安装—c... 安装目录一、cuda安装1.1、cuda版本选择1.2、下载安装二、cudnn安装三、pytorch...
MySQL基础-多表查询 文章目录MySQL基础-多表查询一、案例及引入1、基础概念2、笛卡尔积的理解二、多表查询的分类1、等...
keil调试专题篇 调试的前提是需要连接调试器比如STLINK。 然后点击菜单或者快捷图标均可进入调试模式。 如果前面...
MATLAB | 全网最详细网... 一篇超超超长,超超超全面网络图绘制教程,本篇基本能讲清楚所有绘制要点&#...
IHome主页 - 让你的浏览... 随着互联网的发展,人们越来越离不开浏览器了。每天上班、学习、娱乐,浏览器...
TCP 协议 一、TCP 协议概念 TCP即传输控制协议(Transmission Control ...
营业执照的经营范围有哪些 营业执照的经营范围有哪些 经营范围是指企业可以从事的生产经营与服务项目,是进行公司注册...
C++ 可变体(variant... 一、可变体(variant) 基础用法 Union的问题: 无法知道当前使用的类型是什...
血压计语音芯片,电子医疗设备声... 语音电子血压计是带有语音提示功能的电子血压计,测量前至测量结果全程语音播报࿰...
MySQL OCP888题解0... 文章目录1、原题1.1、英文原题1.2、答案2、题目解析2.1、题干解析2.2、选项解析3、知识点3...
【2023-Pytorch-检... (肆十二想说的一些话)Yolo这个系列我们已经更新了大概一年的时间,现在基本的流程也走走通了,包含数...
实战项目:保险行业用户分类 这里写目录标题1、项目介绍1.1 行业背景1.2 数据介绍2、代码实现导入数据探索数据处理列标签名异...
记录--我在前端干工地(thr... 这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 前段时间接触了Th...
43 openEuler搭建A... 文章目录43 openEuler搭建Apache服务器-配置文件说明和管理模块43.1 配置文件说明...