赞
踩
二叉树的结构体为:
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){}
};
【题目描述】:
给定一个二叉树,判断其是否是一个有效的二叉搜索树。
假设一个二叉搜索树具有如下特征:
【分析】:
INT_MIN < root->val < INT_MAX
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/validate-binary-search-tree
class Solution {
public:
bool isValidBST(TreeNode* root) {
return dfs(root, INT_MIN, INT_MAX);
}
bool dfs(TreeNode* root, long long minv, long long maxv) {
if (!root) return true;
if (root->val < minv || root->val >maxv) return false;
return dfs(root->left, minv, root->val - 1ll) && dfs(root->right, root->val + 1ll, maxv);
}
};
【题目描述】:给定一个二叉树的根节点 root ,返回它的 中序 遍历。
【分析】:
将整棵树的最左边一条链压入栈中,每次取出栈顶元素,如果它有右子树,则将右子树压入栈中。
【C++代码】:
class Solution { public: vector<int>inorderTraversal(TreeNode* root) { vector<int> res; stack<TreeNode*> stk; auto p = root; while (p || stk.size()) { while (p) { //将整棵树的最左边一条链压入栈中 stk.push(p); p = p->left; } p = stk.top(); stk.pop(); //取出栈顶元素 res.push_back(p->val); //放入容器中 p = p->right; //遍历右子树,压入栈中 } return res; } };
概念:stack是一种先进后出的数据结构(First In Last Out),它只有一个出口
栈中只有栈顶元素才可以被外界使用,因此栈不允许有遍历行为
栈中进入数据称为 —入栈push
栈中弹出数据称为 —出栈pop
功能描述:栈容器常用的对外接口
构造函数:
stack<T> stk; //stack采用模板类实现,stack对象的默认构造形式
stack(const stack&stk); //拷贝构造函数
赋值操作:
push(elem); //向栈顶添加元素
pop(); //从栈顶移除第一个元素
top(); //返回栈顶元素
大小操作:
empty(); //判断栈是否为空
size(); //返回栈的大小
【题目描述】:给定一个二叉树,检查它是否是镜像对称的。
【分析】:
1、两个根节点的值要相等
2、左边的左子树和右边的右子树对称
3、左边的右子树和右边的左子树对此
递归方法:
【C++代码】:
class Solution {
public:
bool isSymmetric(TreeNode* root) {
if (!root) return true;
return dfs(root->left, root->right);
}
bool dfs(TreeNode* p, TreeNode* q) {
if (!p || !q) return !q && !p;
//1、两个根节点的值要相等 p->val == q->val
//2、左边的左子树和右边的右子树对此dfs(p->left, q->right)
//3、左边的右子树和右边的左子树对此dfs(p->right, q->left)
return p->val == q->val && dfs(p->left, q->right) && dfs(p->right, q->left);
}
};
迭代方法:
【分析】:
左边:左中右遍历
将整棵树的最左边一条链压入栈中,每次取出栈顶元素,如果它有右子树,则将右子树压入栈中。
右边:右中左遍历
将整棵树的最右边一条链压入栈中,每次取出栈顶元素,如果它有左子树,则将左子树压入栈中。
【C++代码】
class Solution { public: bool isSymmetric(TreeNode* root) { if(!root) return true; stack<TreeNode*>leftStk,rightStk; auto l = root->left,r = root->right; while(l||r||leftStk.size()||rightStk.size()){ while(l&&r){ leftStk.push(l),l = l->left; rightStk.push(r),r = r->right; } if(l||r) return false; l = leftStk.top(),leftStk.pop(); r = rightStk.top(),rightStk.pop(); if(l->val != r->val) return false; l = l->right, r = r->left; } return true; } };
【题目描述】:请完成一个函数,输入一个二叉树,该函数输出它的镜像。
【分析】:
【C++代码】
class Solution {
public:
TreeNode* mirrorTree(TreeNode* root) {
if(!root) return nullptr;
mirrorTree(root->left);
mirrorTree(root->right);
swap(root->left,root->right);
return root;
}
};
【题目描述】:根据一棵树的前序遍历与中序遍历构造二叉树。
【分析】: 前序遍历的第一个数字是root,前序遍历root->left的个数和中序遍历root->left个数相等。
【C++代码】:
class Solution { public: unordered_map<int,int> pos; TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) { int n = preorder.size(); for(int i = 0;i < n;i++){ pos.insert(make_pair(inorder[i],i)); } return dfs(preorder,inorder,0,n-1,0,n-1); } TreeNode* dfs(vector<int>&preorder,vector<int>&inorder,int pl,int pr,int il,int ir){ if(pl > pr) return nullptr; int k = pos[preorder[pl]]; int len = k-il; auto root = new TreeNode(preorder[pl]); root->left = dfs(preorder,inorder,pl+1,pl+len,il,k-1); root->right = dfs(preorder,inorder,pl+len+1,pr,k+1,ir); return root; } };
【题目描述】:给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。
【分析】:
【C++代码】:
class Solution { public: vector<vector<int>> levelOrder(TreeNode* root) { vector<vector<int>> res; if (!root) return res; queue<TreeNode*>q; q.push(root); while (q.size()) { int len = q.size(); vector<int> level; for (int i = 0; i < len; i++) { auto t = q.front(); q.pop(); level.push_back(t->val); if (t->left)q.push(t->left); if (t->right)q.push(t->right); } res.push_back(level); } return res; } };
概念:queue是一种先进先出(First In First Out)的数据结果
队列容器允许从一端新增元素,从另一端移除元素
队列中只有队头和队尾才可以被外界使用,因此队列不允许有遍历行为
队列中进数据称为 —入队push
队列中出数据称为 —出队pop
功能描述:栈容器常用的对外接口
构造函数
queue<T> que; //que采用模板类实现,queue对象的默认构造形式
queue(const queue &que); //拷贝构造函数
赋值操作:
queue& operator=(cosnt queue&que); //重载等号操作符
数据存取
push(elem); //往队尾添加元素
pop(); //从队头移除第一个元素
back(); //返回最后一个元素
front(); //返回第一个元素
大小操作:
empty(); //判断堆栈是否为空
size(); //返回栈的大小
【题目描述】:给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
【C++代码】:
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
//如果以root为根的子树中包含p和q,则返回它们的最近公共祖先
//如果只包含p,则返回p
//如果只包含q,则返回q
//如果不包含,则返回nullptr
if(!root||root==p||root ==q) return root;
auto left = lowestCommonAncestor(root->left,p,q);
auto right= lowestCommonAncestor(root->right,p,q);
if(!left) return right;
if(!right) return left;
return root;
}
};
【题目描述】:给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。
【分析】: 枚举最高点,递归时需要计算,从当前节点往下走,深度的最大值
【C++代码】:
class Solution {
public:
int ans = 0;
int diameterOfBinaryTree(TreeNode* root) {
dfs(root);
return ans;
}
int dfs(TreeNode* root) {
if (!root) return 0;
int left = dfs(root->left);
int right = dfs(root->right);
ans = max(ans, left + right);
return max(left + 1, right + 1);
}
};
【题目描述】:路径 被定义为一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列。该路径 至少包含一个 节点,且不一定经过根节点。
路径和 是路径中各节点值的总和。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/binary-tree-maximum-path-sum
【分析】: 枚举最高点
class Solution { public: int ans = INT_MIN; int maxPathSum(TreeNode* root) { dfs(root); return ans; } //返回从root向下走的最大值 int dfs(TreeNode *root){ if(!root) return 0; int left = dfs(root->left); int right = dfs(root->right); ans = max(ans,left+root->val + right); return max(0,root->val+max(left,right)); } };
【题目描述】:实现一个二叉搜索树迭代器。你将使用二叉搜索树的根节点初始化迭代器。
调用 next() 将返回二叉搜索树中的下一个最小的数。
【C++代码】:
class BSTIterator { public: stack<TreeNode*> stk; BSTIterator(TreeNode* root) { while(root){ stk.push(root); root = root->left; } } int next() { auto p = stk.top(); stk.pop(); int res = p->val; p = p->right; while(p){ stk.push(p); p = p->left; } return res; } bool hasNext() { return !stk.empty(); } };
注意:一般情况下只有前序遍历,并不能唯一确定一棵二叉树
有前序遍历+中序遍历,就可以唯一确定一个二叉树
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Codec { public: // Encodes a tree to a single string. string serialize(TreeNode* root) { string res; dfs1(root,res); return res; } inline void dfs1(TreeNode* root,string& res){ if(!root){ res +="#,"; return ; } res +=to_string(root->val) +','; dfs1(root->left,res); dfs1(root->right,res); } // Decodes your encoded data to tree. TreeNode* deserialize(string data) { int u = 0; return dfs2(data,u); } TreeNode* dfs2(string&data,int &u){ if(data[u]=='#'){ u +=2; return nullptr; } int t =0; bool is_minus = false; if(data[u] == '-'){ is_minus = true; u++; } while(data[u] !=','){ t = t*10 + data[u] -'0'; u++; } u++; if(is_minus) t= -t; auto root = new TreeNode(t); root->left = dfs2(data,u); root->right = dfs2(data,u); return root; } }; // Your Codec object will be instantiated and called as such: // Codec ser, deser; // TreeNode* ans = deser.deserialize(ser.serialize(root));
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。