一、二叉树遍历
二叉树节点定义
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
1、前序遍历
①递归方法
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> S;
if(root == nullptr) return S;
preOrder(root,S);
return S;
}
void preOrder(TreeNode* root,vector<int> &S){
if(root != nullptr){
S.push_back(root->val);
preOrder(root->left,S);
preOrder(root->right,S);
}
}
};
②迭代方法
使用stack容器:栈
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> ret;
if(root == nullptr) return ret;
stack<TreeNode*> s; //创建栈
s.push(root); //将根节点加入栈
while(!s.empty()){
TreeNode* temp = s.top(); //用一个临时变量存储栈顶元素
s.pop(); //出栈
ret.push_back(temp->val);
if(temp->right) s.push(temp->right);
if(temp->left) s.push(temp->left);
}
return ret;
}
};
2、中序遍历
递归写法只需要改变顺序
下面为迭代写法
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> ret;
stack<TreeNode*> s;
while(root != nullptr || !s.empty()){
while(root){
s.push(root);
root = root->left;
}
if(!s.empty()){
root = s.top();
ret.push_back(root->val);
s.pop();
root = root->right;
}
}
return ret;
}
};
3、后序遍历
递归写法只需要改变顺序
下面为迭代写法
思路:前序遍历,先走右边,得到的结果再反转即为后序遍历。
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> ret;
if(root == nullptr) return ret;
stack<TreeNode*> s;
s.push(root);
while(!s.empty()){
TreeNode* temp = s.top();
s.pop();
ret.push_back(temp->val);
if(temp->left) s.push(temp->left);
if(temp->right) s.push(temp->right);
}
for(int i = 0;i<ret.size()/2;i++){
int temp = ret[i];
ret[i] = ret[ret.size() - i -1];
ret[ret.size() - i -1] = temp;
}
return ret;
}
};
4、层序遍历
使用队列容器queue
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> ret;
if(root == nullptr) return ret;
queue<TreeNode*> q;
q.push(root);
while(!q.empty()){
int size = q.size();
ret.push_back(vector<int> ());
for(int i = 0;i<size ;i++){
ret.back().push_back(q.front()->val);
if(q.front()->left) q.push(q.front()->left);
if(q.front()->right) q.push(q.front()->right);
q.pop();
}
}
return ret;
}
};
二、递归问题
1、二叉树最大深度
给定一个二叉树,找出其最大深度。
二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
说明: 叶子节点是指没有子节点的节点。
思路:最大深度=左子树最大深度和右子树最大深度+1;
class Solution {
public:
int maxDepth(TreeNode* root) {
if(root == nullptr) return 0;
int MaxLeftDepth=0;
int MaxRightDepth=0;
if(root->left) MaxLeftDepth = maxDepth(root->left);
if(root->right) MaxRightDepth = maxDepth(root->right);
return MaxLeftDepth >= MaxRightDepth ? MaxLeftDepth+1 : MaxRightDepth+1;
}
};
2、判断轴对称二叉树
class Solution {
public:
bool isSymmetric(TreeNode* root) {
return isEqual(root->left,root->right);
}
bool isEqual(TreeNode* t1,TreeNode* t2){
if(t1 == nullptr && t2 == nullptr) return true;
//if(t1->right == nullptr && t2->left != nullptr) return false;
if(t1 == nullptr || t2 == nullptr) return false;
return (t1->val == t2->val) && isEqual(t1->left, t2->right) && isEqual(t1->right, t2->left);
}
};
3、路径总和
给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。
叶子节点 是指没有子节点的节点。
思路:递归,从上往下遍历,然后targetSum减去当前节点的val
终止条件:如果遍历到空节点返回false,如果遍历到叶子节点,则判断总和是否为0
class Solution {
public:
bool hasPathSum(TreeNode* root, int targetSum) {
if(root == nullptr) return false;
if(root->left == nullptr && root->right == nullptr) return root->val == targetSum;
return hasPathSum(root->left,targetSum-root->val) || hasPathSum(root->right,targetSum-root->val);
}
};
4、将有序数组转换为二叉搜索树
class Solution {
public:
TreeNode* Insert(vector<int>& nums,int left,int right){
if(right < left) return nullptr;
int mid = left + (right - left+1)/2; //这里一定要+1,否则mid不对
TreeNode* root = new TreeNode(nums[mid]);
root->left = Insert(nums,left,mid-1);
root->right = Insert(nums,mid+1,right);
return root;
}
TreeNode* sortedArrayToBST(vector<int>& nums) {
if(nums.size() == 0) return nullptr;
return Insert(nums,0,nums.size()-1);
}
};