目录
1.二叉树深度,平衡,对称
2.二叉树遍历
3.构造二叉树
4.二叉搜索树
5.最近公共祖先
6.路径和
一个二叉树的节点定义为:
struct TreeNode
{
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int v): val(v), left(nullptr), right(nullptr){}
};
1. 二叉树深度,平衡,对称
- 求二叉树最大深度
int maxDepth(TreeNode* root)
{
if (!root) return 0;
return 1 + max(maxDepth(root->left), maxDepth(root->right));
}
- 求二叉树最小深度
int minDepth(TreeNode* root)
{
if (!root) return 0;
if (!root->left) return 1+minDepth(root->right);
if (!root->right) return 1+minDepth(root->left);
return 1+min(minDepth(root->left), minDepth(root->right));
}
- 判断二叉树是否平衡
bool isBalanced(TreeNode* root)
{
if(!root) return 0;
int left = maxDepth(root->left);
int right = maxDepth(root->right);
return abs(left-right) <= 1 && isBalanced(root->left) && isBalanced(root->right);
}
- 判断二叉树是否对称
bool isSymmetric(TreeNode* root) {
if (!root)
return true;
return isSymmetric(root->left, root->right);
}
bool isSymmetric(TreeNode* left, TreeNode* right)
{
if(!left || !right)
return left==right;
if(left->val != right->val)
return false;
return isSymmetric(left->left, right->right) && isSymmetric(left->right, right->left);
}
2. 二叉树遍历
二叉树遍历每个元素可通过广度优先(层次遍历,锯齿形遍历)或深度优先(前序遍历,中序遍历,后序遍历)。
- 层次遍历(level order traversal)
vector<int> levelOrderTrv(TreeNode* root)
{
vector<int> res;
queue<TreeNode*> qu;
qu.push(root);
while (!qu.empty())
{
TreeNode* curr = qu.front()
res.push_back(curr->val);
if (!curr->left) qu.push(curr->left);
if (!curr->right) qu.push(curr->right);
qu.pop();
}
return res;
}
- 锯齿形遍历(zig-zag traversal)
vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
vector<vector<int>> res;
if(!root)
return res;
queue<TreeNode*> q;
q.push(root);
bool leftToRight = true;
while(!q.empty())
{
int size = q.size();
vector<int> lev(size);
for(int i = 0; i < size; i++)
{
TreeNode* node = q.front();
q.pop();
int index = leftToRight ? i : (size - 1 - i);
lev[index] = node->val;
if(node->left)
q.push(node->left);
if(node->right)
q.push(node->right);
}
leftToRight = !leftToRight;
res.push_back(lev);
}
return res;
}
- 前序遍历(pre-order traversal)
递归法:
vector<int> preOrderTrv(TreeNode* root)
{
vector<int> res;
preOrder(root, res);
return res;
}
void preOrder(TreeNode* root, vector<int> res)
{
if (!root) return;
res.push_back(root->val);
preOrder(root->left);
preOrder(root->right);
}
迭代法:
vector<int> preOrderTrv(TreeNode* root)
{
vector<int> res;
stack<TreeNode*> st;
TreeNode* curr = root;
st.push(curr);
while (!st.empty())
{
curr = st.top();
res.push_back(curr->val);
st.pop();
if (curr->right) st.push(curr->right);
if (curr->left) st.push(curr->left);
}
return res;
}
- 中序遍历(in-order traversal)
递归法:
vector<int> inOrderTrv(TreeNode* root)
{
vector<int> res;
inOrder(root, res);
return res;
}
void inOrder(TreeNode* root, vector<int> res)
{
if (!root) return;
res.push_back(root->val);
inOrder(root->left);
inOrder(root->right);
}
迭代法:
vector<int> inOrderTrv(TreeNode* root)
{
vector<int> res;
stack<TreeNode*> st;
TreeNode* curr = root;
while (!curr || !st.empty())
{
while (!curr)
{
st.push(curr);
curr = curr->left;
}
curr = st.top();
st.pop();
res.push_back(curr->val);
curr = curr->right;
}
return res;
}
- 后序遍历(post-order traversal)
递归法:
vector<int> postOrderTrv(TreeNode* root)
{
vector<int> res;
postOrder(root, res);
return res;
}
void postOrder(TreeNode* root, vector<int> res)
{
if (!root) return;
res.push_back(root->val);
postOrder(root->left);
postOrder(root->right);
}
迭代法:
vector<int> postOrderTrv(TreeNode* root)
{
vector<int> res;
stack<TreeNode*> s1;
stack<TreeNode*> s2;
s1.push(root);
while (!s1.empty())
{
TreeNode* curr = s1.top();
s1.top();
s2.push(curr);
if (curr->left) s1.push(curr->left);
if (curr->right) s1.push(curr->right);
}
while (!s2.empty())
{
TreeNode* node = s2.top();
res.push_back(node->val);
s2.pop();
}
return res;
}
3. 构造二叉树
- 由前序和中序遍历数组构造二叉树
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
return build(preorder, 0, preorder.size()-1,
inorder, 0, inorder.size()-1);
}
TreeNode* build(vector<int>& preorder, int pStart, int pEnd,
vector<int>& inorder, int iStart, int iEnd)
{
if(pStart > pEnd)
return nullptr;
TreeNode* node = new TreeNode(preorder[pStart]);
int index;
for(int i = iStart; i <= iEnd; i++)
{
if(inorder[i] == node->val)
{
index = i;
break;
}
}
node->left = build(preorder, pStart+1, pStart + index - iStart, inorder, iStart, index-1);
node->right = build(preorder, pStart + index - iStart+1, pEnd, inorder, index+1, iEnd);
return node;
}
- 由中序和后序遍历数组构造二叉树
TreeNode *buildTree(vector<int> &inorder, vector<int> &postorder) {
return build(inorder, 0, inorder.size() - 1, postorder, 0, postorder.size() - 1);
}
TreeNode* build(vector<int> &inorder, int iStart, int iEnd, vector<int> &postorder, int pStart, int pEnd){
if(pStart > pEnd){
return nullptr;
}
TreeNode* node = new TreeNode(postorder[pEnd]);
int index;
for(int i = iStart; i <= iEnd; i++){
if(inorder[i] == node->val){
index = i;
break;
}
}
node->left = build(inorder, iStart, index - 1, postorder, pStart, pStart + index - iStart - 1);
node->right = build(inorder, index + 1, iEnd, postorder, pEnd - iEnd + index, pEnd - 1);
return node;
}
4. 二叉搜索树
- 验证二叉搜索树
bool isValidBST(TreeNode* root) {
return isValidBST(root, LONG_MIN, LONG_MAX);
}
bool isValidBST(TreeNode* root, long min, long max)
{
if(!root)
return true;
if(root->val <= min || root->val >= max)
return false;
return isValidBST(root->left, min, root->val) && isValidBST(root->right, root->val, max);
}
- 将有序数组转化为二叉搜索树
TreeNode *sortedArrayToBST(vector<int> &num) {
if(num.size() == 0) return NULL;
if(num.size() == 1)
{
return new TreeNode(num[0]);
}
int middle = num.size()/2;
TreeNode* root = new TreeNode(num[middle]);
vector<int> leftInts(num.begin(), num.begin()+middle);
vector<int> rightInts(num.begin()+middle+1, num.end());
root->left = sortedArrayToBST(leftInts);
root->right = sortedArrayToBST(rightInts);
return root;
}
- 二叉搜索树第K小的元素
int kthSmallest(TreeNode* root, int k) {
stack<TreeNode*> st;
while(true)
{
while(root)
{
st.push(root);
root = root->left;
}
root = st.top();
st.pop();
if(--k == 0)
return root->val;
root = root->right;
}
}
5. 最近公共祖先
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(!root || root == p || root == q)
return root;
TreeNode* left = lowestCommonAncestor(root->left, p, q);
TreeNode* right = lowestCommonAncestor(root->right, p, q);
if(left && right)
return root;
return left ? left : right;
}
6. 路径和
- 是否有一和为给定值的根-节点路径
bool hasPathSum(TreeNode* root, int sum) {
if(!root)
return false;
if(root->val == sum && !root->left && !root->right)
return true;
return hasPathSum(root->left, sum - root->val) ||
hasPathSum(root->right, sum - root->val);
}
- 找出所有和为给定值的根-节点路径
vector<vector<int>> pathSum(TreeNode* root, int sum) {
vector<vector<int>> paths;
vector<int> path;
findPaths(root, sum, path, paths);
return paths;
}
void findPaths(TreeNode* root, int sum, vector<int> &path, vector<vector<int>> &paths)
{
if (!root) return;
path.push_back(root->val);
if (!(root->left) && !(root->right) && sum == root->val)
paths.push_back(path);
findPaths(root->left, sum-root->val, path, paths);
findPaths(root->right, sum-root->val, path, paths);
path.pop_back();
}