Leetcode分类解析(二叉树)

持续更新中…

1.二叉树中序遍历

94.Binary Tree Inorder Traversal 二叉树中序遍历
98.Validate Binary Search Tree 验证二叉搜索树
1.指定一个最小值LONG_MIN; 2.中序遍历过程中如果出现降序,返回false; 3.过程中没有返回false,最后返回true。

bool isValidBST(TreeNode* root) {
    long res=LONG_MIN;//这里要注意是long类型的,
    while(p || !S.empty())//中序遍历
    {
        ...
        if(p->val <= res)
            return false;
        else
            res=p->val;
        ...
    }
    return true;
}

99. Recover Binary Search Tree 恢复二叉搜索树
1.中序遍历找到被交换的两个节点的指针(0,2,4);2.交换相应节点的值。

void recoverTree(TreeNode* root);//恢复二叉搜索树
vector<TreeNode*> Inorder(TreeNode* root){//中序遍历
    vector<TreeNode*> v;//存放被交换的节点值
    TreeNode* p=root, *tmp=NULL
    while(!s.empty() || p)
    {
        ...
        if(!tmp)//很重要
                tmp=p;
        else 
        {
            if(tmp->val > p->val)
            {
                v.push_back(tmp);
                v.push_back(p);    
            }
            tmp=p;
        }
        ... 
    }
}

2.层遍历

102 Binary Tree Level Order Traversal 二叉树的层次遍历
100.Same Tree 相同的树
1.递归:前序递归到底,if(!p || !q) return p==q;否则p->val == q->val,左右递归

bool isSameTree(TreeNode* p, TreeNode* q) {
if(!p || !q)
    return p==q;//同为空才是true
return (p->val == q->val && isSameTree(p->left, q->left) && isSameTree(p->right, q->right));

2.非递归:用queue,
1.两个树层遍历过程中,如果值不相等返回false;2.左儿子均不为空则入队;3.左儿子一个空一个不空则返回false;4.右儿子同理;5.不满足while出循环,如果两个队列均为空返回true,否则返回false。

while(!Q1.empty() && !Q2.empty())
{  
   ...
   if(p1->val!=p2->val)//1.
       return false;
   if(p1->left && p2->left)//2.
       入队;
   else if(!(!p1->left && !p2->left))//3.
        return false;           
    4.右儿子同理 
   }  
if(Q1.empty() && Q2.empty()) //5.
    return true;  
return false;

101.Symmetric Tree 对称二叉树
递归:1.因为要判断同一层上的,所以需要->left和->right同步!!!2.递归先序遍历,1.if(!l && !r) return true; 2.if(!l || !r)return false; 3.if (l->val != r->val) return false;

bool isSymmetric(TreeNode* l,TreeNode* r) {
   if(!l && !r)
       return true;
   if(!l || !r)
       return false;
//注意:if (l->val == r->val) return true;是不对的,因为不能有一层是true就返回true,递归层
   if (l->val != r->val) 
       return false;
   return isSymmetric(l->left,r->right) && isSymmetric(l->right, r->left);    
}
bool isSymmetric(TreeNode* root) {
    if(!root)
        return true;
    return isSymmetric(root->left, root->right);
}

2.非递归:因为要判断同一层上的,所以需要->left和->right同步,所以就需要两个队列了!!!并且在入队列的时候,NULL也入,Q1从左到右,而Q2从右到左!!!(判断两个树相同NULL节点不用入队,只要儿子NULL不一样就返回false;而对于对称性,左->中间节点可能存在NULL,NULL也入队,不用管儿子。)

while(!Q1.empty() && !Q2.empty())
{
    ...
    if(!p1 && !p2)//1.均为NULL
        continue;
    if(!p1 || !p2)//2.一NULL一非NULL
        return false;
    if(p1->val!=p2->val)//3.
        return false;
    Q1.push(p1->left);//4.先左后右,NULL也入队
    Q1.push(p1->right);
    Q2.push(p2->right);//5.先右后左,NULL也入队
    Q2.push(p2->left);
}
if(Q1.empty() && Q2.empty())
    return true;
else
    return false;

103.Binary Tree Zigzag Level Order Traversal 二叉树的回环层次遍历
1.flag标志确定本层是从左到右还是从右到左,本层结束取反即可;
2.v提前初始化为count个0,本层遍历过程中v[i]=即可

bool flag=true;
while(!Q.empty())
{
    vector<int> vi(count,0);//count
    for(int i=0;i<count;++i)
    {
        ...
        int index = flag ? i : count-i-1;
        vi[index]=p->val;
        ...
   }
   flag=!flag;
}

107.Binary Tree Level Order Traversal II 值自底向上的层次遍历
1.先求深度;2.层遍历最后一层插入第一层的值即可,然后循环

int depth(TreeNode *root){//后序遍历
    if (!root) 
        return 0;
    return max(depth(root->left),depth(root->right))+1;
}
int d= depth(root);
vector<vector<int> > v(d,vector<int>{});
while(!Q.empty())
{
    while(count)
    {
        ...
        v[d-1].push_back(p->val);//最后一层插入第一层的值即可
        ...
        --count;  
    }
    --d;
}

116.Populating Next Right Pointers in Each Node 每个节点的右向指针

while(!Q.empty())
{
    while(count)
    {
        ...
        if(count==1)//count为1,next指针为NULL;
            p->next=NULL;
        else
            p->next=q.front();
        ...
        --count;  
    }
}

199.Binary Tree Right Side View 二叉树的右视图
打印每层最右边的节点的值即可

while(!Q.empty())
{
    while(count)
    {
        ...
        if(count == n)
            v.push_back(p->val);
        ...
        --count;  
    }
}

515. Find Largest Value in Each Tree Row 在每个树行中找最大值
层遍历即可
637. Average of Levels in Binary Tree 二叉树的层平均值
层遍历即可

3.like前序遍历(去的过程中做事,回来返回每一层结果值)和like后序遍历(去的过程中不做事,回来的过程中做事并返回值)

144.Binary Tree Preorder Traversal 二叉树的前序遍历
145.Binary Tree Postorder Traversal 二叉树的后序遍历
104.Maximum Depth of Binary Tree 二叉树的最大深度

int depth(TreeNode *root){//后序遍历
    if (!root) 
        return 0;
    return max(depth(root->left),depth(root->right))+1;
}

111.Minimum Depth of Binary Tree 二叉树的最小深度

int minDepth(TreeNode* root) {//后序遍历
    if(!root)
        return 0;
    int L=minDepth(root->left);
    int R=minDepth(root->right);
    //最小高度不是0,就选 min(L,R),否则选最大max(L,R)
    return (min(L,R) ? min(L,R) : max(L,R)) + 1;
}

110. Balanced Binary Tree 平衡二叉树
1.开新函数,传递depth;2.后序遍历计算每一层的高度差值depth。

bool isBalanced(TreeNode* root) {
    if(!root)
        return true;
    int depth=0;
    return isBalanced(root,depth);
}
bool isBalanced(TreeNode* root,int& depth) {//后序遍历
    if(!root)
        return true;
    int diff=0,l=0,r=0;//都会经过isBalanced函数从而改变depth;
    if(isBalanced(root->left,l) && isBalanced(root->right,r))//本层的满足返回true;
    {
        diff=abs(l-r);
        depth=max(l,r)+1;
        if(diff<=1)//满足平衡就返回true
            return true;
    }
    return false;//本层不满足就返回false
}

112.Path Sum 路径总和
如果左右儿子均为NULL,返回:root->val==sum;
否则每一层减去该层val值,继续递归;

bool hasPathSum(TreeNode* root, int sum) {//前序遍历
    if(!root)
        return false;
    if(!root->left && !root->right)
        return root->val==sum;
    return hasPathSum(root->left,sum-root->val) || hasPathSum(root->right,sum-root->val);
}

113.Path Sum II 找到所有从根到叶路径总和等于给定总和的路径
未完待续…

129.Sum Root to Leaf Numbers 求根叶数字 总和
1.开新函数,传递subsum参数;2.前序遍历,上一层和(subsum)加上本层的值:subsum*10+root->val

int sumNumbers(TreeNode* root) {
    return sum(root, 0);
}
int sum(TreeNode*root, int subsum) //需要子函数,父*10+子   //前序遍历
{
    if(!root)   
        return 0;
    if(!root->left && !root->right) 
        return subsum*10+root->val;
    return sum(root->left, subsum*10+root->val)+sum(root->right, subsum*10+root->val);
}

226.Invert Binary Tree 翻转二叉树
前序遍历,交换左右儿子即可

TreeNode* invertTree(TreeNode* root) {
   if(!root)
        return NULL;
    TreeNode* tmp=root->left;
    root->left=root->right;
    root->right=tmp;
    invertTree(root->left);
    invertTree(root->right);
    return root;
}

4.构造二叉树

105.Construct Binary Tree from Preorder and Inorder Traversal 从前序与中序遍历序列构造二叉树
每次从 preorder 头部取一个值 mid,作为树的根节点检查 mid 在 inorder 中的位置;则mid 前面部分将作为 树的左子树,右部分作为树的右子树
左子树:
先序:左子根节点;右子根节点
中序: 左子树的最左节点,当前根节点
右子树:
先序:右子根节点;右子树最后一个节点的尾后节点
中序:右子树的最左节点;右子树最后一个节点的尾后节点
前序构造
preorder: 8 [4 3 3 7] [5]
inorder: [3 3 4 7] 8 [5]

TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
    return helper(preorder,0,preorder.size(),inorder,0,inorder.size());
}
TreeNode* helper(vector<int>& preorder,int pi,int pj,vector<int>& inorder,int ii,int ij){
//前序构造
    if(pi >= pj || ii >= ij)

    int mid = preorder[pi];//1.preorder找到mid位置;pi为当前根节点位置
    auto f = find(inorder.begin() + ii,inorder.begin() + ij,mid);//2.inorder找到mid位置
    int nf = f - (inorder.begin() + ii);//3.以mid为根节点的左子树节点个数

    TreeNode* root = new TreeNode(mid);    
    root -> left = helper(preorder, pi + 1, pi + 1 + nf,   inorder, ii, ii + nf); 
    root -> right = helper(preorder, pi + 1 + nf, pj,   inorder, ii + nf + 1, ij);

    return root;
}

106.Construct Binary Tree from Inorder and Postorder Traversal 从中序与后序遍历序列构造二叉树
每次取postorder的最后一个值mid,将其作为树的根节点;
然后从inroder中找到mid,将其分割成为两部分,左边作为mid的左子树,右边作为mid的右子树。
先序构造
Inorder : [3 4 6] 8 [9 10 11]
postorder: [3 6 4] [9 11 10] 8

TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {        
    return helper(inorder,0,inorder.size(),postorder,0,postorder.size());
}
TreeNode* helper(vector<int>& inorder,int i,int j,vector<int>& postorder,int ii,int jj)
{//先序构造
    if(i >= j || ii >= jj)
        return NULL;

    int mid = postorder[jj - 1];//1.postorder中mid的位置
    auto f = find(inorder.begin() + i,inorder.begin() + j,mid);//2.inorder中mid的位置
    int nf = f - inorder.begin() - i;//3.以mid为根节点的左子树节点个数

    TreeNode* root = new TreeNode(mid);
    root -> left = helper(inorder,i,i + nf,postorder,ii,ii + nf);
    root -> right = helper(inorder,i + nf + 1,j,postorder,ii + nf,jj - 1);

    return root;
}

108. Convert Sorted Array to Binary Search Tree 将有序数组转换为二叉搜索树
开新函数递归;找到中间的作为每次根节点,保证平衡,然后先序构造

TreeNode* sortedArrayToBST(vector<int>& nums) {
    return sortedArrayToBST(nums, 0,nums.size()-1);
    //1.这里可以为:nums.size(),相应的下面的函数也需要改变
}
TreeNode* sortedArrayToBST(vector<int>& nums, int i, int j)
{//先序构造
    if(i >= j) 
        return NULL; 
    //找到中间的作为每次根节点,保证平衡,然后先序遍历
    int mid=(i+j)/2;

    TreeNode* root=new TreeNode(nums[mid]);
    root->left=sortedArrayToBST(nums, i, mid);//2.就在这改为mid-1
    root->right=sortedArrayToBST(nums, mid+1,j);
    return root;
}

5.二叉树祖先问题

235.Lowest Common Ancestor of a Binary Search Tree 二叉搜索树的最近公共祖先
分三种情况:
1.左右各一个;(else return cur;)
2.都在左边,cur=cur->left;(p->val < cur->val && q->val < cur->val)
3.都在右边,cur=cur->right;(p->val > cur->val && q->val > cur->val)

TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
    TreeNode* cur=root;
    while(cur)
    {
        if(p->val < cur->val && q->val < cur->val)
            cur=cur->left;
        else if(p->val > cur->val && q->val > cur->val)
            cur=cur->right;
        else
            return cur;
    }
}

236. Lowest Common Ancestor of a Binary Tree 二叉树的最近公共祖先
1.后序递归过程中,碰到p,q(root == p || root == q || root == NULL) 就返回root到上一层;
2.否则继续递归,一直到底,left和right均不为空,返回root到上一层,否则返回非空的到上一层。

TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
    if (root == p || root == q || root == NULL) 
       return root;//递归到这截止(root || NULL)!!!
    TreeNode *left = lowestCommonAncestor(root->left, p, q);
    TreeNode *right = lowestCommonAncestor(root->right, p, q);
    //left && right 就返回 root,否则返回非空的那一个!!!
    return left && right ? root : left ? left : right;
}

6.其他类型题

96. Unique Binary Search Trees 节点组成的不同的二叉搜索树有多少种
动态规划:
1.f[i]表示:有i个节点时,它有多少种不同形态的树
2.f[i]=sum[i=0->i-1] f[i] * f[i-j-1];这里i-1-j 减掉的1代表是根节点占了一个位置
3.f[0]=1,f[1]=1;

int numTrees(int n) {
    if(n==0 || n==1)
        return 1;
    vector<int> f(n+1,0);
    f[0]=1;//初始值
    f[1]=1;//初始值
    for (int i = 2; i <= n; ++i) 
    {
        int t = 0;
        for (int j = 0; j < i; ++j)
            t += f[j] * f[i-j-1];
        f[i]=t;
    }
    return f[n];
}

114. Flatten Binary Tree to Linked List 二叉树转换链表

    1
   / \
  2   5
 / \   \
3   4   6
1
    \
     2
      \
       3
        \
         4
          \
           5
            \
             6

非递归,不用栈!
解析:从树的右到左…

void flatten(TreeNode* root) {
    while (root) 
    {
        if (root->left && root->right) 
        {
            TreeNode* p = root->left;
            while (p->right)
                p = p->right;
            p->right = root->right;
        }
        if(root->left)
            root->right = root->left;
        root->left = NULL;
        root = root->right;
    }
}

222. Count Complete Tree Nodes 完全二叉树的节点个数
1.求高度;
2.有大于一层的节点数:求最后一层的节点个数

p = root;
level = h - 2;
while(level >= 0){
    (1)找到**左子树**最后一层的**最右边**的节点!
    (2)left!=NULL时:说明左子树是满的,节点个数为:count+=2^level,再去计算右子树(p = p->right;)!
    (3)否则 left!=NULL时:说明最后一层左子树就不满,就去计算左左子树(p = p->left;)!
    (4)--level;  
}

3.最后一层看还有别的节点时(最后一层节点个数为单数的时候)++count;
4.return (1 << (h - 1)) + count - 1;(1 << level为:2^level)。
具体代码如下:

int countNodes(TreeNode* root) {
    if(!root) 
        return 0;
    TreeNode *p = root;
    int h = 0, count = 0, level;
    while(p) //1.求高度
    {
        p = p->left;
        h++;
    }

    p = root;
    level = h - 2;
    while(level >= 0) //2.求最后一层的节点个数!!!
    {
        TreeNode* left = p->left;

        for(int i = 0;i < level;i ++) //1.找到left子树最后一层的最右边的节点!
            left = left->right;
        if(left) //2.左子树是满的,就去计算右子树!
        {
            p = p->right;
            count += (1 << level);//3.就是2^level
        } 
        else //4.left==NULL说明最后一层左子树就不满,就去计算左左子树!
            p = p->left;
        --level;       
    }
    if(p) //3.此时就是一个根节点!!!
        count++;
    return (1 << (h - 1)) + count - 1;
}

230. Kth Smallest Element in a BST 二叉搜索树中第K小的元素
中序遍历:if(–k == 0) return p->val;即可!!!

int kthSmallest(TreeNode* root, int k) {
    if(!root)
        exit(-1);
    while(p || !s.empty())
    {
        ...
        if(--k == 0)//找到第k小的value
            return p->val;
        ...
    }
}

1.二叉树中序遍历

94.Binary Tree Inorder Traversal 二叉树中序遍历
98.Validate Binary Search Tree 验证二叉搜索树
99. Recover Binary Search Tree 恢复二叉搜索树

2.层遍历

102 Binary Tree Level Order Traversal 二叉树的层次遍历
100.Same Tree 相同的树
101.Symmetric Tree 对称二叉树
103.Binary Tree Zigzag Level Order Traversal 二叉树的回环层次遍历
107.Binary Tree Level Order Traversal II 值自底向上的层次遍历
116.Populating Next Right Pointers in Each Node 每个节点的右向指针
199.Binary Tree Right Side View 二叉树的右视图
515. Find Largest Value in Each Tree Row 在每个树行中找最大值
637. Average of Levels in Binary Tree 二叉树的层平均值

3.前序遍历和后序遍历

144.Binary Tree Preorder Traversal 二叉树的前序遍历
145.Binary Tree Postorder Traversal 二叉树的后序遍历
104.Maximum Depth of Binary Tree 二叉树的最大深度
111.Minimum Depth of Binary Tree 二叉树的最小深度
110. Balanced Binary Tree 平衡二叉树
112.Path Sum 路径总和
113.Path Sum II 找到所有从根到叶路径总和等于给定总和的路径
129.Sum Root to Leaf Numbers 求根叶 数字 总和
226.Invert Binary Tree 翻转二叉树

4.构造二叉树

105.Construct Binary Tree from Preorder and Inorder Traversal 从前序与中序遍历序列构造二叉树
106.Construct Binary Tree from Inorder and Postorder Traversal 从中序与后序遍历序列构造二叉树
108.Convert Sorted Array to Binary Search Tree 将有序数组转换为二叉搜索树

5.二叉树祖先问题

235.Lowest Common Ancestor of a Binary Search Tree 二叉搜索树的最近公共祖先
236. Lowest Common Ancestor of a Binary Tree 二叉树的最近公共祖先

6.其他类型题

96. Unique Binary Search Trees 节点组成的不同的二叉搜索树有多少种
114. Flatten Binary Tree to Linked List 二叉树转换链表
222. Count Complete Tree Nodes 完全二叉树的节点个数
230. Kth Smallest Element in a BST 二叉搜索树中第K小的元素

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值