0
点赞
收藏
分享

微信扫一扫

LeetCode 有关二叉树的算法题目(C++)


0、NULL与nullptr的区别

在C语言中,​​NULL​​​通常被定义为:​​#define NULL ((void *)0)​​​。因为在C语言中把空指针赋给​​int​​​和​​char​​​指针的时候,发生了隐式类型转换,把​​void​​指针转换成了相应类型的指针。

所以说​​NULL​​​实际上是一个空指针。在C++中,​​NULL​​​实际上是​​0​​​。因为C++中不能把​​void*​​类型的指针隐式转换成其他类型的指针。

在C++11版本中特意引入了​​nullptr​​​这一新的关键字可以保证在任何情况下都代表空指针,以后用​​nullptr​​​替代​​NULL​​​,而​​NULL​​​就当做​​0​​使用。

1、二叉树的前序遍历

问题描述

给定一个二叉树,返回它的 前序 遍历。

示例:

输入: [1,null,2,3]  
1
\
2
/
3

输出: [1,2,3]

代码实现

/**
* 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 {
public:
vector<int> ivec;
vector<int> preorderTraversal(TreeNode* root) {
if(root){
ivec.push_back(root->val);
if(root->left)
preorderTraversal(root->left);
if(root->right)
preorderTraversal(root->right);
}
return ivec;
}
};

运行截图

LeetCode 有关二叉树的算法题目(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 {
public:
vector<int> preorderTraversal(TreeNode* root) {
if(root == NULL)
return {};
stack<TreeNode*> s;
vector<int> v;
TreeNode* p = root;
while(p or s.size()){
if(p){
v.push_back(p->val);
s.push(p);
p = p->left;
}
else{
p = s.top();
s.pop();
p = p->right;
}
}
return v;
}
};

运行截图

LeetCode 有关二叉树的算法题目(C++)_二叉树_02

2、二叉树的中序遍历

问题描述

给定一个二叉树,返回它的中序 遍历。

示例:

输入: [1,null,2,3]
1
\
2
/
3

输出: [1,3,2]

代码实现

/**
* 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 {
public:
vector<int> ivec;
vector<int> inorderTraversal(TreeNode* root) {
if(root){
if(root->left)
inorderTraversal(root->left);
ivec.push_back(root->val);
if(root->right)
inorderTraversal(root->right);
}
return ivec;
}
};

运行截图

LeetCode 有关二叉树的算法题目(C++)_结点_03

二叉树中序遍历非递归算法

/**
* 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 {
public:
vector<int> inorderTraversal(TreeNode* root) {
if(root == NULL)
return {};
stack<TreeNode*> s;
vector<int> v;
TreeNode* p = root;
while(p or s.size()){
if(p){
s.push(p);
p = p->left;
}
else{
p = s.top();
s.pop();
v.push_back(p->val);
p = p->right;
}
}
return v;
}
};

运行截图

LeetCode 有关二叉树的算法题目(C++)_二叉树_04

3、二叉树的后序遍历

问题描述

给定一个二叉树,返回它的 后序 遍历。

示例:

输入: [1,null,2,3]  
1
\
2
/
3

输出: [3,2,1]

代码实现

/**
* 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 {
public:
vector<int> ivec;
vector<int> postorderTraversal(TreeNode* root) {
if(root){
if(root->left)
postorderTraversal(root->left);
if(root->right)
postorderTraversal(root->right);
ivec.push_back(root->val);
}
return ivec;
}
};

运行截图

LeetCode 有关二叉树的算法题目(C++)_代码实现_05

二叉树后序遍历的非递归算法

/**
* 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 {
public:
vector<int> postorderTraversal(TreeNode* root) {
if(root == NULL)
return {};
stack<TreeNode*> s;
vector<int> v;
TreeNode *p = root, *pre = NULL;
while(p or s.size()){
if(p){
s.push(p);
p = p->left;
}
else{
p = s.top();
if(p->right && pre != p->right){
p = p->right;
}
else{
v.push_back(p->val);
s.pop();
pre = p;
p = NULL;
}
}
}
return v;
}
};

运行截图

LeetCode 有关二叉树的算法题目(C++)_代码实现_06

4、二叉树的层序遍历

问题描述

给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。

示例:

二叉树:​​[3,9,20,null,null,15,7]​​,

3
/ \
9 20
/ \
15 7

返回其层次遍历结果:

[
[3],
[9,20],
[15,7]
]

解题思路

  • 与以往的求二叉树的层序遍历略有不同。本题目的含义是将每层的二叉树结点存储到二维数组中。
  • 就可以利用一个整型变量记录此时的队列中的元素个数,也就是某一层的元素个数。
  • 当队头元素的孩子结点入队后,队头元素出队,记录元素个数的变量减一,直到该变量减为0,说明某一层的结点全部出队。
  • 循环直到队列中没由元素为止。

代码实现

/**
* 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 {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
if(root == NULL)
return {};
queue<TreeNode*> treeque; // 建立二叉树类型的队列
vector<vector<int>> allLevelVec; //存储层序遍历的数组
vector<int> eveLevelVec; // 存储每层的数组
treeque.push(root); // 根结点入队
while(treeque.size()){
int num = treeque.size(); // 记录当前队列中的元素个数
while(num){
eveLevelVec.push_back(treeque.front()->val); // 队头元素进入容器
num--; // 队列中元素个数减一
if(treeque.front()->left) // 队头元素左孩子不空 入队
treeque.push(treeque.front()->left);
if(treeque.front()->right) // 队头元素右孩子不空 入队
treeque.push(treeque.front()->right);
treeque.pop(); // 队头元素出队
}
allLevelVec.push_back(eveLevelVec);
eveLevelVec.clear();
}
return allLevelVec;
}
};

运行截图

LeetCode 有关二叉树的算法题目(C++)_结点_07

本题相似题解——二叉树的层平均值

给定一个非空二叉树, 返回一个由每层节点平均值组成的数组.

示例 1:

输入:

3
/ \
9 20
/ \
15 7

输出: [3, 14.5, 11]
解释:
第0层的平均值是 3, 第1层是 14.5, 第2层是 11. 因此返回 [3, 14.5, 11].

代码实现

/**
* 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 {
public:
vector<double> averageOfLevels(TreeNode* root) {
vector<double> dvec;
queue<TreeNode*> q;
q.push(root);
while(q.size()){
int num1 = q.size(), num2 = q.size();
double d = 0;
while(num1){
d += q.front()->val;
num1--;
if(q.front()->left)
q.push(q.front()->left);
if(q.front()->right)
q.push(q.front()->right);
q.pop();
}
dvec.push_back(d/num2);
}
return dvec;
}
};

运行截图

LeetCode 有关二叉树的算法题目(C++)_结点_08

5、平衡二叉树(包含求二叉树高度)

给定一个二叉树,判断它是否是高度平衡的二叉树。

本题中,一棵高度平衡二叉树定义为:

一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。

示例 1:

给定二叉树 [3,9,20,null,null,15,7]

3
/ \
9 20
/ \
15 7

返回 true 。

示例 2:

给定二叉树 [1,2,2,3,3,null,null,4,4]

1
/ \
2 2
/ \
3 3
/ \
4 4

返回 false 。

代码实现

/**
* 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 {
public:
int GetTreeDepth(TreeNode* root) { // 求二叉树的高度
if(root == NULL)
return 0;
int leftDepth = GetTreeDepth(root->left);
int rightDepth = GetTreeDepth(root->right);
return (leftDepth > rightDepth ? leftDepth : rightDepth) + 1;
}
bool isBalanced(TreeNode* root) {
if(root == NULL)
return true;
bool leftBalance = true, rightBalance = true;
if(abs(GetTreeDepth(root->left) - GetTreeDepth(root->right)) > 1)
return false;
leftBalance = isBalanced(root->left);
rightBalance = isBalanced(root->right);
return leftBalance && rightBalance;
}
};

运行截图

LeetCode 有关二叉树的算法题目(C++)_二叉树_09

6、对称二叉树

问题描述

给定一个二叉树,检查它是否是镜像对称的。

例如,二叉树 ​​[1,2,2,3,4,4,3]​​是对称的。

1
/ \
2 2
/ \ / \
3 4 4 3

但是下面这个​​[1,2,2,null,3,null,3]​​则不是镜像对称的:

1
/ \
2 2
\ \
3 3

代码实现

/**
* 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 {
public:
bool isMirror(TreeNode* leftRoot, TreeNode* rightRoot){
if(leftRoot == NULL && rightRoot == NULL) //左右孩子为空 符合镜像条件
return true;
if(leftRoot == NULL || rightRoot == NULL)// 一个空 一个不空 显然不符合题意
return false;
return leftRoot->val == rightRoot->val // 左右孩子不空 结点值必须一致
&& isMirror(leftRoot->left, rightRoot->right)
&& isMirror(leftRoot->right, rightRoot->left);
}
bool isSymmetric(TreeNode* root) {
if(root == NULL)
return true;
return isMirror(root->left, root->right);
}
};

LeetCode 有关二叉树的算法题目(C++)_二叉树_10

7、二叉树的最小深度

问题描述

给定一个二叉树,找出其最小深度。

最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

说明: 叶子节点是指没有子节点的节点。

示例:

给定二叉树 ​​[3,9,20,null,null,15,7]​​,

3
/ \
9 20
/ \
15 7

返回它的最小深度​​2​​。

解题思路

与求二叉树最大高度不同,求最小深度要考虑到单支树的最小高度不是1,而是有树枝的那边的高度。

代码实现

/**
* 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 {
public:

int minDepth(TreeNode* root) {
if(root == NULL)
return 0;
int minLeftDepth = minDepth(root->left);
int minrightDepth = minDepth(root->right);
if(root->left == NULL || root->right == NULL)
return minLeftDepth + minrightDepth + 1;
return min(minLeftDepth, minrightDepth) + 1;
}
};

运行截图

LeetCode 有关二叉树的算法题目(C++)_代码实现_11

8、二叉树的直径

给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。

示例 :
给定二叉树

1
/ \
2 3
/ \
4 5

返回 ​​3​​​, 它的长度是路径​​[4,2,1,3]​​​或者 ​​[5,2,1,3]​​。

注意: 两结点之间的路径长度是以它们之间边的数目表示。

解题思路

与求树高的算法类似,树高是根结点到叶子结点的最多结点数。本题是求任意两点的最大连接边的数目,是有一定区别的。

代码实现

/**
* 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 {
public:
int maxdiameter(TreeNode* root, int &num){
if(root == NULL)
return 0;
int l = maxdiameter(root->left, num);
int r = maxdiameter(root->right, num);
num = max(num, l + r);
return max(l ,r) + 1;
}
int diameterOfBinaryTree(TreeNode* root) {
int num = 0;
maxdiameter(root, num);
return num;
}
};

运行截图

LeetCode 有关二叉树的算法题目(C++)_代码实现_12

9、相同的树

问题描述

给定两个二叉树,编写一个函数来检验它们是否相同。

如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

示例 1:

输入:       1         1
/ \ / \
2 3 2 3

[1,2,3], [1,2,3]

输出: true

示例 2:

输入:      1          1
/ \
2 2

[1,2], [1,null,2]

输出: false

示例 3:

输入:       1         1
/ \ / \
2 1 1 2

[1,2,1], [1,1,2]

输出: false

代码实现

/**
* 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 {
public:
bool isSameTree(TreeNode* p, TreeNode* q) {
if(p == NULL and q == NULL)
return true;
if(p == NULL or q == NULL)
return false;
return p->val == q->val and isSameTree(p->left, q->left) and isSameTree(p->right, q->right);
}
};

运行截图

LeetCode 有关二叉树的算法题目(C++)_二叉树_13

10、路径总和

给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。

说明: 叶子节点是指没有子节点的节点。

示例:
给定如下二叉树,以及目标和 ​​​sum = 22​​,

5
/ \
4 8
/ / \
11 13 4
/ \ \
7 2 1

返回​​true​​​, 因为存在目标和为​​22​​​的根节点到叶子节点的路径 ​​5->4->11->2​​。

/**
* 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 {
public:
bool hasPathSum(TreeNode* root, int sum) {
if(root == NULL)
return false;
sum -= root->val;
if(root->left == NULL and root->right == NULL)
return sum == 0;
return hasPathSum(root->left, sum) or hasPathSum(root->right, sum);

}
};

运行截图

LeetCode 有关二叉树的算法题目(C++)_代码实现_14

11、路径总和 II

问题描述

给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。

说明: 叶子节点是指没有子节点的节点。

示例:
给定如下二叉树,以及目标和 ​​​sum = 22​​,

5
/ \
4 8
/ / \
11 13 4
/ \ / \
7 2 5 1

返回:

[
[5,4,11,2],
[5,8,4,5]
]

解题思路

以先序遍历思想为核心,没遍历一个结点均压入容器,遇到叶子结点后比较路径长度和sum值,记录所有符合题意的路径。

代码实现

/**
* 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 {
public:
bool isEqualSum(vector<int>& itmp, const int sum){
if(itmp.size() == 0)
return false;
return accumulate(itmp.begin(), itmp.end(), 0) == sum;
}

void findPathNode(TreeNode* root, vector<vector<int>> &ivec, vector<int>& itmp, int sum){
if(root){
itmp.push_back(root->val);
if(root->left == NULL and root->right == NULL and isEqualSum(itmp, sum))
ivec.push_back(itmp);
if(root->left)
findPathNode(root->left, ivec, itmp, sum);
if(root->right)
findPathNode(root->right, ivec, itmp, sum);
}
if(itmp.size())
itmp.pop_back();
}

vector<vector<int>> pathSum(TreeNode* root, int sum) { // 主函数
if(root == NULL)
return {};
vector<vector<int>> ivec;
vector<int> itmp;
findPathNode(root, ivec, itmp, sum);
return ivec;
}
};

运行截图

LeetCode 有关二叉树的算法题目(C++)_代码实现_15

12、二叉树的所有路径

问题描述

给定一个二叉树,返回所有从根节点到叶子节点的路径。

说明: 叶子节点是指没有子节点的节点。

示例:

输入:

1
/ \
2 3
\
5

输出:​​["1->2->5", "1->3"]​

解释: 所有根节点到叶子节点的路径为: ​​1->2->5, 1->3​​。

解题思路

  • 一定要注意被调用函数中的参数在什么情况下是引用传递,什么情况下是值传递。对于本题的写法,一定要用值传递。保证​​string s​​在每次迭代中的记忆性。
  • ​to_string()​​函数将变量转化为string类型。

代码实现

/**
* 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 {
public:
void allpaths(TreeNode* root, vector<string> &svec, string s){
if(root){
s += to_string(root->val);
if(root->left == NULL and root->right == NULL)
svec.push_back(s);
else{
s += "->";
allpaths(root->left, svec, s);
allpaths(root->right, svec, s);
}
}

}
vector<string> binaryTreePaths(TreeNode* root) {
if(root == NULL)
return {};
vector<string> svec;
string s;
allpaths(root, svec, s);
return svec;
}
};

LeetCode 有关二叉树的算法题目(C++)_结点_16

13、从前序与中序遍历序列构造二叉树

问题描述

根据一棵树的前序遍历与中序遍历构造二叉树。

注意:
你可以假设树中没有重复的元素。

例如,给出

前序遍历 ​​preorder = [3,9,20,15,7]​​​ 中序遍历​​inorder = [9,3,15,20,7]​​ 返回如下的二叉树:

3
/ \
9 20
/ \
15 7

代码实现

/**
* 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 {
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if(preorder.empty() or inorder.empty())
return nullptr;
TreeNode* root = new TreeNode(preorder[0]);
int pos = 0;
for(; pos < preorder.size(); pos++)
if(preorder[0] == inorder[pos])
break;

vector<int> preorder_left(preorder.begin() + 1, preorder.begin() + pos + 1);
vector<int> preorder_right(preorder.begin() + pos + 1, preorder.end());
vector<int> inorder_left(inorder.begin(), inorder.begin() + pos);
vector<int> inorder_right(inorder.begin() + pos + 1, inorder.end());

root->left = buildTree(preorder_left, inorder_left);
root->right = buildTree(preorder_right, inorder_right);
return root;
}
};

运行截图

LeetCode 有关二叉树的算法题目(C++)_二叉树_17

14、从中序与后序遍历序列构造二叉树

问题描述

根据一棵树的中序遍历与后序遍历构造二叉树。

注意:
你可以假设树中没有重复的元素。

例如,给出

中序遍历​​inorder = [9,3,15,20,7]​​​ 后序遍历​​postorder = [9,15,7,20,3]​​ 返回如下的二叉树:

3
/ \
9 20
/ \
15 7

代码实现

/**
* 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 {
public:
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
if(inorder.empty() or postorder.empty())
return nullptr;
int n = postorder.size();
TreeNode* root = new TreeNode(postorder[n - 1]);
int pos = n - 1;
for(; pos >= 0; pos--)
if(inorder[pos] == postorder[n - 1])
break;

vector<int> inorder_left(inorder.begin(), inorder.begin() + pos + 1);
vector<int> inorder_right(inorder.begin() + pos + 1, inorder.end());
vector<int> postorder_left(postorder.begin(), postorder.begin() + pos);
vector<int> postorder_right(postorder.begin() + pos, postorder.end() - 1);

root->left = buildTree(inorder_left, postorder_left);
root->right = buildTree(inorder_right, postorder_right);

return root;
}
};

运行截图

LeetCode 有关二叉树的算法题目(C++)_代码实现_18


举报

相关推荐

0 条评论