码迷,mamicode.com
首页 > 其他好文 > 详细

二叉树 + 递归 + 分治法总结

时间:2019-08-20 18:29:33      阅读:90      评论:0      收藏:0      [点我收藏+]

标签:max   找不到   param   def   ring   左右   现在   最长路径   info   

二叉树递归相关题目的时间复杂度基本上都是O(n) = 一共有n个点 + 每个点的时间复杂度(1)

而二叉树分治法最坏的时间复杂度为O(n^2)

 

时间复杂度:T(n) = 2T(n/2) + O(1) = O(n)

Merge Sort, Quick Sort: T(n) = 2T(n/2) + O(n) = O(nlogn)

技术图片

 

前序遍历:

 技术图片

 

解法一:递归,通常是设置一个全局变量来保存结果。

/**
 * 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:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> result;
        traverse(root, result);
        return result;
    }
    void traverse(TreeNode* root, vector<int>& res){
        //递归终止条件
        if(root == NULL)
            return;
        res.push_back(root->val);
        traverse(root->left, res);
        traverse(root->right, res);
    }
};

解法二:Divide & Conquer

 技术图片

 

/**
 * 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:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> res;
        if(root == NULL)
            return res;
        
        //divide
        vector<int> left = preorderTraversal(root->left);
        vector<int> right = preorderTraversal(root->right);
        
        //conquer
        res.push_back(root->val);
        for(auto i : left)
            res.push_back(i);
        for(auto i : right)
            res.push_back(i);
        return res;
    }
};

 解法三:非递归版本C++

采用堆栈实现。

  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:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> res;
        if(root == NULL)
            return res;
        stack<TreeNode*> st;
        st.push(root);
        while(!st.empty()){
            TreeNode* node = st.top();
            st.pop();
            res.push_back(node->val);
            if(node->right)
                st.push(node->right);
            if(node->left)
                st.push(node->left);
        }
        return res;
    }
};

 

中序遍历:

技术图片

 一. 递归

/**
 * 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:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> res;
        if(root == NULL)
            return res;
        stack<TreeNode*> st;
        st.push(root);
        while(!st.empty()){
            TreeNode* node = st.top();
            st.pop();
            res.push_back(node->val);
            if(node->right)
                st.push(node->right);
            if(node->left)
                st.push(node->left);
        }
        return res;
    }
};

二. Divide and Quaqer

/**
 * 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:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        if(root == NULL)
            return res;
        
        vector<int> left = inorderTraversal(root->left);
        vector<int> right = inorderTraversal(root->right);
        
        for(int i : left)
            res.push_back(i);
        res.push_back(root->val);
        for(int i: right)
            res.push_back(i);
        
        return res;
    }
};

三. 非递归,用栈来实现。

栈或者当前结点不为空时:

1)把当前结点压入栈中,然后继续压入它的左结点,直到左结点为空;

2)将栈顶元素的值保存在res中,并弹出;

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:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        stack<TreeNode* > st;
        TreeNode* cur = root;
        while(cur || !st.empty()){
            while(cur){
                st.push(cur);
                cur = cur->left;
            }
            cur = st.top();
            st.pop();
            res.push_back(cur->val);
            cur = cur->right;
        }
        return res;
    }
};

 

后序遍历:

技术图片

一.

/**
 * 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:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> res;
        traverse(root, res);
        return res;
    }
    void traverse(TreeNode* root, vector<int>& res){
        if(root == NULL)
            return;
        traverse(root->left, res);
        traverse(root->right, res);
        res.push_back(root->val);
    }
};

 

二.

/**
 * 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:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> res;
        if(root == NULL)
            return res;
       
        vector<int> left = postorderTraversal(root->left);
        vector<int> right = postorderTraversal(root->right);
        
        for(int i: left)
            res.push_back(i);
        for(int i: right)
            res.push_back(i);
        res.push_back(root->val);
        
        return res;
    }
};

 

三.

/**
 * 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:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> res;
        stack<TreeNode* > st;
        if(root == NULL)
            return res;
        st.push(root);
        while(!st.empty()){
            TreeNode* tmp = st.top();
            st.pop();
            res.insert(res.begin(), tmp->val);   //在前端插入
            if(tmp->left)
                st.push(tmp->left);
            if(tmp->right)
                st.push(tmp->right);
        }
        return res;
    }
};

 

技术图片

 

 一.

/**
 * 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 {
private:
    int dep_max;    //全局变量
public:
    int maxDepth(TreeNode* root) {
        dep_max = 0;
        helper(root, 1);  //1为当前根结点
        return dep_max;  
         
    }
    void helper(TreeNode* root, int depth){
        if(root==NULL) return;
        
        dep_max = max(dep_max, depth);
        helper(root->left, depth+1);
        helper(root->right, depth+1);
    }
};

二.

/**
 * 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:
    int maxDepth(TreeNode* root) {
        if(root==NULL) return 0;
        
        //左右子树的深度
        int left = maxDepth(root->left);
        int right = maxDepth(root->right);

        return max(left, right)+1;  
         
    }

    
};

平衡二叉树:左右子树高度相差不超过1

技术图片

 

/**
 * 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:
    bool isBalanced(TreeNode* root) {
        if(root==NULL)
            return true;
        if(abs(getDepth(root->left) - getDepth(root->right)) > 1)
            return false;
        return isBalanced(root->left) && isBalanced(root->right);
    }
    int getDepth(TreeNode* root){
        if(!root)
            return 0;
        return max(getDepth(root->left), getDepth(root->right)) + 1;
    }
    
};

上面的方法使得每个结点都会被上面的点计算深度时访问一次,优化一下:若发现某个结点的子树不平衡,则不计算它的深度,直接返回-1

/**
 * 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:
    bool isBalanced(TreeNode* root) {
        if(depth(root) == -1)
            return false;
        return true;
    }
    int depth(TreeNode* root){
        if(!root)
            return 0;
        int left = depth(root->left);
        if(left==-1)
            return -1;
        int right = depth(root->right);
        if(right == -1)
            return -1;
        int dif = abs(left - right);
        if(dif>1)
            return -1;
        else
            return max(left, right)+1;
    }
};

 

技术图片

二叉搜索树的性质是:左子树的值 < 根节点 < 右子树的值

 

/**
 * 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(p->val > q->val)
            swap(p,q);   // ensure p < q
        
        while(root){
            if(root->val < p->val)
                root = root->right;
            else if(root->val > q->val)
                root = root->left;
            else
                return root;
        }
        return NULL;
    }
};

 

已知A和B的父亲结点:

 技术图片

技术图片

技术图片

思路:把A和A的父结点保存在set中,若在B及B的父结点中找到一个和set中相同的结点,就返回这个公共祖先。

 

/**
 * Definition of ParentTreeNode:
 * class ParentTreeNode {
 * public:
 *     int val;
 *     ParentTreeNode *parent, *left, *right;
 * }
 */


class Solution {
public:
    /*
     * @param root: The root of the tree
     * @param A: node in the tree
     * @param B: node in the tree
     * @return: The lowest common ancestor of A and B
     */
    ParentTreeNode * lowestCommonAncestorII(ParentTreeNode * root, ParentTreeNode * A, ParentTreeNode * B) {
        // write your code here
        if(root == NULL)
            return NULL;
            
        unordered_set<ParentTreeNode*> s;  //保存A向上的路径
        while(A!=NULL){
            s.insert(A);
            A = A->parent;
        }
        
        while(B){
            if(s.find(B) == s.end())
                //s中找不到相同的结点
                B = B->parent;
            else
                return B;
        }
        
    }
};

 

未知p,q的父亲结点:

技术图片

分治法:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
//若找到了LCA,就返回LCA,即 p和q出现在一左一右,返回它的根结点
//若只找到n1, 就返回n1
//若只找到了n2, 就返回n2
//若都不存在,返回NULL
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(root == NULL)
            return NULL;
        if(root == p || root == q)
            return root;
        
        //divide
        TreeNode* left = lowestCommonAncestor(root->left, p, q);
        TreeNode* right = lowestCommonAncestor(root->right, p, q);
        
        //Conquer
        if(left != NULL && right != NULL)
            return root;
        
        if(left != NULL)
            return left;
        
        if(right != NULL)
            return right;
        
        return NULL;
    }
};

 

 

/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = NULL;
 *     }
 * }
 */
//一颗二叉树,求从根结点到叶子结点的路径的最大值;求从根结点到任一结点的路径的最大值
class Solution {
public:
    /**
     * @param root: The root of binary tree.
     * @return: An integer
     */
    int maxPathSum(TreeNode * root) {
        // write your code here
        if (root == NULL)
            return 0;
        int left = maxPathSum(root->left);
        int right = maxPathSum(root->right);

        //root -> leaf
        //return max(left, right) + root->val;

        //root-> anynode
        return max(0, max(left, right)) + root->val;
    }
};

 

从任一结点到任一结点路径的最大值:

技术图片

 

参考链接:https://www.geeksforgeeks.org/find-maximum-path-sum-in-a-binary-tree/

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
//any to any node: 最长路径的位置:完全在左边;完全在右边;跨过根结点
 //O(n)
class Solution {
public:
    int findMax(TreeNode* root, int &res){
        if(root == NULL)
            return 0;
        
        int l = findMax(root->left, res);
        int r = findMax(root->right, res);
        
        int max_single = max(max(l, r)+root->val, root->val);
        int max_round = max(max_single, l+r+root->val);
        
        res = max(res, max_round);   //store the maximum result
        return max_single;
    }
    
    int maxPathSum(TreeNode* root) {
        int res = INT_MIN;
        findMax(root, res);
        return res;
    }
};

 

 技术图片

 

/**
 * 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:
    vector<string> binaryTreePaths(TreeNode* root) {
        vector<string> res;
        if(root == NULL)
            return res;   //返回空vector res
        
        if(root->left==NULL && root->right==NULL)
            res.push_back(to_string(root->val));
        
        //divide
        vector<string> left = binaryTreePaths(root->left);
        vector<string> right = binaryTreePaths(root->right);
        
        //conquer
        for(string s : left)
            res.push_back(to_string(root->val) + "->" + s);
        for(string s : right)
            res.push_back(to_string(root->val) + "->" + s);
        
        return res;
        
    }
};

 

二叉树 + 递归 + 分治法总结

标签:max   找不到   param   def   ring   左右   现在   最长路径   info   

原文地址:https://www.cnblogs.com/Bella2017/p/11384471.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!