Leetcode分类解析(二叉树)

原创 2018年04月16日 15:28:02

持续更新中…

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());
}
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);
    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小的元素

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qiangzhenyi1207/article/details/79961237

[LeetCode]二叉树题目总结

【LeetCode】二叉树习题个人总结 近一个月来,刷了不少LeetCode题目。但是总还是感觉提高的不多,自己最初想的一边做一边总结的初衷也没有正常执行,今晚静下心来,总结一下和二叉树有关的题目。...
  • loveRooney
  • loveRooney
  • 2014年06月19日 20:30
  • 3919

LeetCode总结,二叉树各种类型问题小结

1,三大基础遍历方式 三个遍历的博客地址, 1) 144/145/94 Binary Tree (Pre & In & Post) order Traversal 即: 前序遍历,总是先访...
  • EbowTang
  • EbowTang
  • 2016年05月24日 10:49
  • 3503

[leetcode-二叉树层次遍历并统计每层节点数]--102. Binary Tree Level Order Traversal

Question 102. Binary Tree Level Order Traversal Given a binary tree, return the level order traver...
  • u010853261
  • u010853261
  • 2017年02月09日 13:22
  • 822

leetcode 二叉树系列搞定

偶尔做几个题这样也就慢慢把leetcode上二叉树系列的题目做完了,一共26个题(sigh...一个收费题没刷) , 二叉树系列的题最普遍的解法就是递归了,所以一般先往递归上想就okay了~ 非递归算...
  • zxasqwedc
  • zxasqwedc
  • 2014年12月09日 10:34
  • 1020

Leetcode算法题分类解析:(一)总览

Leetcode算法题分类解析:(一)总览1.为何/如何刷题1.1 必要性刷题刷题,从“刷”字就能看出其中的机械性和应试性,但这就是几乎所有IT公司面试中的一环。尽管面试者可能也对这种考察方式不是很满...
  • dc_726
  • dc_726
  • 2016年06月17日 23:01
  • 6538

Leetcode 655. Print Binary Tree 打印二叉树 解题报告

给一个二叉树,要求进行打印,也就是在一个高度*宽度的矩阵里面打印就好了,每个子树的root打印在当前子区间的中间就好了Print a binary tree in an m*n 2D string a...
  • MebiuW
  • MebiuW
  • 2017年08月15日 22:03
  • 869

[数据结构][Leetcode]翻转二叉树

1.问题描述Invert a binary tree.For example: to Google: 90% of our engineers use the software you wr...
  • u014359097
  • u014359097
  • 2015年12月08日 22:16
  • 2341

LeetCode 刷题之二:寻找二叉树的最大深度

题目为: Given a binary tree, find its maximum depth. The maximum depth is the number of nodes a...
  • longshengguoji
  • longshengguoji
  • 2014年12月12日 23:17
  • 2498

leetcode | 二叉树的前序遍历、中序遍历、后续遍历的非递归实现

Binary Tree Preorder Traversal:https://leetcode.com/problems/binary-tree-preorder-traversal/ Binary...
  • quzhongxin
  • quzhongxin
  • 2015年06月01日 19:20
  • 1646

leetCode|二叉树题目总结

Invert Binary TreeInvert a binary tree.Recursion:class Solution { public: TreeNode* invertTree(T...
  • DouMiaoO_Oo
  • DouMiaoO_Oo
  • 2016年04月21日 23:07
  • 777
收藏助手
不良信息举报
您举报文章:Leetcode分类解析(二叉树)
举报原因:
原因补充:

(最多只允许输入30个字)