LeetCode---二叉树3-总结例题

二叉树-总结例题

1-从中序与后序遍历序列构造二叉树

给定二叉树的后序遍历和二叉树的中序遍历
想法:

  1. 先根据后序遍历的最后一个元素构造根节点
  2. 寻找根节点在中序遍历中的位置
  3. 递归构建根节点的左右子树
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        if(inorder.size() == 0 || postorder.size() == 0)
            return NULL;
        int _is = 0;
        int _ie = inorder.size()-1;
        int _ps = 0;
        int _pe = postorder.size()-1;
        return build(inorder,postorder,_is,_ie,_ps,_pe);

    }
    // 构建节点的递归函数
    TreeNode* build(vector<int>& inorder, vector<int>& postorder,int is,int ie,int ps,int pe)
    {
        // 构建根节点
        TreeNode* ans = new TreeNode(postorder[pe]);
        int ll = 0;
        int rl = 0;
        for(int i = is ; i <= ie ; ++i )
        {
            if(inorder[i] == postorder[pe])
            {
                // 左子树长度
                ll = i - is;
                // 右子树长度
                rl = ie - i;
            }
        }
        // 构建左子树
        if ( ll > 0 )
        {
            ans->left = build(inorder,postorder,is,is+ll-1,ps,ps+ll-1);
        }
        // 构建右子树
        if ( rl > 0 )
        {
            ans->right = build(inorder,postorder,ie-rl+1,ie,pe-rl,pe-1);
        }
        return ans;
    }
};

总结:

  1. 返回类型为pointer,异常情况可以直接返回NULL
  2. 上面的代码里用了两个变量,ll和rl分别表示,左右子树在vector里面的长度。
  3. 每次调用递归函数,都用ll和rl改变两个容器的首尾下标。

2-从前序与中序遍历序列构造二叉树

想法:

  1. 先根据先序遍历的最后一个元素构造根节点
  2. 寻找根节点在中序遍历中的位置
  3. 递归构建根节点的左右子树
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        return build(inorder,preorder,0,inorder.size()-1,0,preorder.size()-1);
    }
    TreeNode* build(vector<int>& inorder,vector<int>& preorder, int is,int ie,int ps,int pe)
    {
        if(inorder.size()==0 || preorder.size()==0)
        {
            return NULL;
        }
        int ll = 0 ;
        int rl = 0 ;
        TreeNode* ans = new TreeNode(preorder[ps]);
        for(int i = is; i<= ie; i++)
        {
            if(preorder[ps]==inorder[i])
            {
                ll = i - is ;
                rl = ie - i;
            }
        }
        if ( ll > 0 )
        {
            ans->left = build (inorder,preorder,is,is+ll-1,ps+1 ,ps+ll );
        }
        if ( rl > 0 )
        {
            ans->right = build(inorder,preorder,ie-rl+1,ie,pe-rl+1,pe);
        }
        return ans;
    }
};

3-填充每个节点的下一个右侧节点指针(完美二叉树)

想法:

  1. 通过层次遍历,使用队列
  2. 每一层的最后一个节点指向next,否则就指向下一个
class Solution {
public:
    Node* connect(Node* root) {
        if( root == NULL)
            return NULL;
        queue<Node*> q;
        q.push(root);
        // 记录每一层的元素个数
        while( ! q.empty())
        {
            int num = q.size();
            // 遍历当前层(队列)里面的每个元素
            for(int i = 0; i < num; i++)
            {
                // p指向 是队列的头节点
                Node* p = q.front();
                // 出队
                q.pop();
                // 如果到当前层最后一个元素了,next指针指向NULL,队未空,next指向队头节点
                if(i == num-1)
                    p->next = NULL;
                else
                    p->next = q.front();
                // p 的左右孩子节点入队
                if( p->left != NULL )
                    q.push( p->left );
                if ( p->right != NULL )
                    q.push( p->right );
            }
        }
        return root;
    }
};

4-填充每个节点的下一个右侧节点指针(非完美二叉树)

我的解法同上。

class Solution {
public:
    Node* connect(Node* root) {
        if( root == NULL)
            return NULL;
        queue<Node*> q;
        q.push(root);
        // 记录每一层的元素个数
        while( ! q.empty())
        {
            int num = q.size();
            // 遍历当前层(队列)里面的每个元素
            for(int i = 0; i < num; i++)
            {
                // p指向 是队列的头节点
                Node* p = q.front();
                // 出队
                q.pop();
                // 如果到当前层最后一个元素了,next指针指向NULL,队未空,next指向队头节点
                if(i == num-1)
                    p->next = NULL;
                else
                    p->next = q.front();
                // p 的左右孩子节点入队
                if( p->left != NULL )
                    q.push( p->left );
                if ( p->right != NULL )
                    q.push( p->right );
            }
        }
        return root;
    }
};

5-二叉树的最近公共祖先

自己的想法 :

  1. 在树中分别查找目标节点。把查找的路径存放到两个栈里。
  2. 其中一个栈依次出栈,在另个栈里查找这个出栈的节点。
  3. Note:因为搜索到的路径是唯一的。
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        stack<TreeNode*> A;
        stack<TreeNode*> B;
        find(root,p,A);
        find(root,q,B);

        vector<int> bb;
        for(int i = 0; i< B.size();++i)
        {
            bb.push_back(B.top()->val);
            B.pop();
        }
        while(!A.empty())
        {
            TreeNode* ans = A.top();
            for(int i = 0 ; i< bb.size();++i)
            {
                if( ans->val == bb[i])
                    return ans;
            }
        }
        return NULL;
    }
    void find (TreeNode* root ,TreeNode* target, stack<TreeNode*> &ss)
    {
        if (! root)
            return ;
        if(root->val == target->val)
        {
            ss.push(root);
        }
        if(root->left != NULL)
        {
            vector<int> lv = dfs(root->left);
            for(int i = 0; i < lv.size() ; ++i )
            {
                if(lv[i] == target->val)
                {
                    ss.push(root->left);
                    find(root->left,target ,ss);
                }
            }
        }
        if(root->right != NULL)
        {
            vector<int> rv = dfs(root->right);
            for(int i = 0; i < rv.size() ; ++i )
            {
                if(rv[i] == target->val)
                {
                    ss.push(root->right);
                    find(root->right,target,ss);
                }
            }
        }
    }

    vector<int> dfs(TreeNode* root)
    {
        vector<int> order;
        helper(root,order);
        return order;
    }
    void helper( TreeNode* root, vector<int>& vv)
    {
        if(root->left!=NULL)
            helper(root->left,vv);
        vv.push_back(root->val);
        if(root->right != NULL)
            helper(root->right,vv);
    }
};
代码超出时间限制

看看人家的代码吧:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(!root || !p || !q)
            return NULL;
        vector<TreeNode*> A;
        vector<TreeNode*> B;
        dfs(root,p,A);
        dfs(root,q,B);

        TreeNode* ans ;
        int len = min(A.size(),B.size());
        for(int i = 0; i < len ; i++)
        {
            if(A[i]->val != B[i]->val)
                break;
            ans = A[i];
        }
        return ans;

    }
    bool dfs(TreeNode* root,TreeNode* target,vector<TreeNode*>& path)
    {
        if( root == target ){
            path.push_back(root);
            return true;
        }
        path.push_back(root);
        if( root->left && dfs( root->left , target,path ))
            return true;
        if(root->right && dfs( root->right , target , path ))
            return true;
        // 回溯???
        path.pop_back();
        return false;
    }

};

问题:

  1. ==在深度遍历函数里,pop_back()的理解:回溯???==
  2. for循环的问题
        for(int i = 0; i < len ; i++)
        {
            if(A[i]->val != B[i]->val)
                break;
            ans = A[i];
        }

原文地址:https://www.cnblogs.com/jiangxinyu1/p/12284995.html

时间: 2024-10-22 14:25:14

LeetCode---二叉树3-总结例题的相关文章

Leetcode:二叉树的前序遍历

Leetcode: 二叉树的前序遍历 最近在复习数据结构, 感觉很多东西都忘得的差不多了,哪怕是看完书再看视频,还是容易忘,所以干脆想着配合leetcode来刷吧,Python实现起来很简单,但是C语言也不能丢,所以C语言和Python一起吧. 题目: 给定一个二叉树,返回它的前序遍历. 输入: [1,null,2,3] 1 2 / 3 输出: [1,2,3] Python 实现 # Definition for a binary tree node. # class TreeNode(obje

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

Binary Tree Preorder Traversal:https://leetcode.com/problems/binary-tree-preorder-traversal/ Binary Tree Inorder Traversal :https://leetcode.com/problems/binary-tree-inorder-traversal/ Binary Tree Postorder Traversal:https://leetcode.com/problems/bin

[C++]封装二叉树(附例题)

[C++]封装二叉树 题目要求 (简单的说,就是把二叉树的功能封装起来) binary tree is a tree data structure in which each node has at most two children, which are referred to as the left child and the right child. Three Constructor: creat a tree by copy. creat a tree by a array.(usin

LeetCode - 二叉树的最大深度

自己解法,欢迎拍砖 给定一个二叉树,找出其最大深度. 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数. 说明: 叶子节点是指没有子节点的节点. 示例:给定二叉树 [3,9,20,null,null,15,7], 3 / 9 20 / 15 7 返回它的最大深度 3 . 解法: 1 int maxDepth(struct TreeNode* root) 2 { 3 if (root == NULL) 4 return 0; 5 if (root->left == NULL &&

(leetcode)二叉树的前序遍历-c语言实现

给定一个二叉树,返回它的 前序 遍历. 示例: 输入: [1,null,2,3] 1 2 / 3 输出: [1,2,3] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? 前序遍历 前序遍历首先访问根节点,然后遍历左子树,最后遍历右子树. 用c语言来实现比较麻烦,现在大概介绍下我的思路,首先题目先要实现一个前序遍历,如果用递归,会比较简单,几行代码就可以实现,但是现在要求使用迭代发来实现.整个遍历过程是,访问根节点,然后遍历其左子树,然后再看左子树是否有其左孩子和右孩子.因为在查看左孩子之后,

(LeetCode)二叉树中和为某一值的路径

原体例如以下: Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum. For example: Given the below binary tree and sum = 22, 5 / 4 8 / / 11 13 4 / \ 7 2 1 return t

LeetCode 二叉树反序遍历(binary-tree-postorder-traversal)

Given a binary tree, return the postorder traversal of its nodes' values. For example:Given binary tree{1,#,2,3}, 1 2 / 3 return[3,2,1]. Note: Recursive solution is trivial, could you do it iteratively? import java.util.*; public class Solution { pub

leetcode 二叉树中序遍历的递归和非递归实现

Given a binary tree, return the inorder traversal of its nodes' values. For example:Given binary tree {1,#,2,3},    1          2     /    3 return [1,3,2]. /**  * Definition for a binary tree node.  * struct TreeNode {  *     int val;  *     TreeNode

LeetCode 数组转二叉树 C#

把LeetCode二叉树题目的测试数组,转换成二叉树 class TreeNode { public int val; public TreeNode left; public TreeNode right; public TreeNode(int x) { val = x; } } class Tree { public static TreeNode CreateNode(int? val) { if (val == null) return null; return new TreeNod

二叉树系列 - 二叉树的深度,例 [LeetCode]

二叉树的深度的概念最值得注意的地方,在于 到"叶子"节点的距离. 一般来说,如果直接说“深度”,都是指最大深度,即最远叶子的距离. 这里放两道例题,最小深度和最大深度. 1. 二叉树的最小深度 Given a binary tree, find its minimum depth. The minimum depth is the number of nodes along the shortest path from the root node down to the nearest