九章算法第三课,二叉树与分治法

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

【背诵】二叉树的递归和非递归遍历方法

97. 二叉树的最大深度
maxDepth返回以当前root为根节点的树的最大深度,出口为叶子的下一层节点深度为0。

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;
    }
};

480. 二叉树的所有路径
函数返回以当前root为根的所有路径组成的vector,出口:1.空节点返回空向量,2.叶子节点只返回节点值形成的字符串而不加->

class Solution {
public:
    vector<string> binaryTreePaths(TreeNode * root) {
         vector<string> res;
         if (root==NULL) return res;
         if (root->left==NULL && root->right==NULL) {res.push_back(to_string(root->val)); return res;}
         vector<string> left=binaryTreePaths(root->left);
         vector<string> right=binaryTreePaths(root->right);
         
         for (int i=0;i<left.size();i++) {
             string tmp=to_string(root->val)+"->"+left[i];
             res.push_back(tmp);
         }
          for (int i=0;i<right.size();i++) {
             string tmp=to_string(root->val)+"->"+right[i];
             res.push_back(tmp);
         }
         
         return res;
    }
};

596. 最小子树
方法一,使用全局变量:

class Solution {
public:
    TreeNode * res;
    int sum;
    TreeNode * findSubtree(TreeNode * root) {
        if (root==NULL) return NULL;
        sum=INT_MAX;
        int sum=sumofSubtree(root);
        return res;
    }
    int sumofSubtree(TreeNode * root){
        if (root==NULL) return 0;
        int left=sumofSubtree(root->left);
        int right=sumofSubtree(root->right);
        if (left+right+root->val<sum) 
           {sum=left+right+root->val;
            res=root;}
        return left+right+root->val;
        }
};

方法二,构造一个新的答案类型:

class ResultType {
public:  
    int minSum;
    int sum;
    TreeNode * node;
    ResultType():minSum(INT_MAX),sum(0),node(NULL) {}
    ResultType(int _minSum,int _sum, TreeNode * _node):minSum(_minSum),sum(_sum),node(_node) {}  
};
class Solution {
public:
    TreeNode * findSubtree(TreeNode * root) {
        if (root==NULL) return NULL;
        return helper(root).node;
    }
    ResultType helper(TreeNode * root){
        if (root==NULL) return ResultType();
        ResultType left=helper(root->left);
        ResultType right=helper(root->right);
        
        ResultType res=ResultType(left.sum+right.sum+root->val,left.sum+right.sum+root->val,root);
        if (left.minSum<res.minSum) {
            res.minSum=left.minSum;
            res.node=left.node;
        }
        if (right.minSum<res.minSum) {
            res.minSum=right.minSum;
            res.node=right.node;
        }
        return res;
    }
};

93. 平衡二叉树

class Solution {
public:
    bool isBalanced(TreeNode * root) {
        if (root==NULL) return true;
        return (depth(root)!=-1);
    }
    int depth(TreeNode * root) {
        if (root==NULL) return 0;
        int left=depth(root->left);
        int right=depth(root->right);
        
        if (right==-1 || left==-1 || abs(right-left)>1)
            return -1;
        else return max(right,left)+1;
    }
};

597. 具有最大平均数的子树
使用ResultType记录以每个节点为根的总和、节点个数(记录平均值会牵扯到小数可能不准确),使用全局变量更新最优结果。

class ResultType {
public:
    int sum,size;
    ResultType():sum(0),size(0) {}
    ResultType(int _sum,int _size):sum(_sum),size(_size) {}
};
class Solution {
private:
    TreeNode* node;
    ResultType data;
public:
    TreeNode * findSubtree2(TreeNode * root) {
        if (root==NULL) return root; 
        data.sum=INT_MIN;
        data.size=INT_MAX;
        helper(root);
        return node;
    }
    ResultType helper(TreeNode * root) {
        if (root==NULL) return ResultType();
        ResultType left=helper(root->left);
        ResultType right=helper(root->right);
        
        ResultType thisnode=ResultType(left.sum+right.sum+root->val,
                                       left.size+right.size+1);
        if (data.sum * thisnode.size <thisnode.sum * data.size) {
            data=thisnode;
            node=root;
        }
        return thisnode;
    }
};

453. 将二叉树拆成链表
方法一,非递归方法:只要这棵树上有左子树就说明没完,找到左子树的最右子树(右子树应该接到的位置),把右子树接过来,左子树变为右子树,左子树赋为NULL。

class Solution {
public:
    void flatten(TreeNode *root) {
        // write your code here
        if (root == NULL) return;  
        while (root) {  
            if (root->left) {  
                TreeNode *pre = root->left;  
                while (pre->right)  
                    pre = pre->right;  
                pre->right = root->right;  
                root->right = root->left;  
                root->left = NULL;  
            }
            root = root->right;
        }  
    }
};

方法二,递归方法。返回的是已经flatten的子树的根节点:

class Solution {
public:
    void flatten(TreeNode *root) {
        // write your code here
        if (root == NULL) return;  
        helper(root);
    }
    TreeNode * helper(TreeNode *root) {
        if (root==NULL) return NULL;
        TreeNode * left=helper(root->left);
        TreeNode * right=helper(root->right);
    
        if (left!=NULL) {
            TreeNode * tmp=left;
            while (tmp->right!=NULL)
                tmp=tmp->right;
            tmp->right=right;
            root->right=left;
            root->left=NULL;
        }
        return root;
    }
};

方法三,另一种递归方法。直接返回左右子树最右下角的位置(应该相接的节点),直接相接,省去了方法二中while循环找最右下角的步骤。

class Solution {
public:
    void flatten(TreeNode* root) {
        helper(root);
    }
    TreeNode* helper(TreeNode* root){
        if (root==NULL) return NULL;
        TreeNode* left=helper(root->left);// left记录了root->left的最右下角的位置,用于接上root->right
        TreeNode* right=helper(root->right);//right 记录了root->right最右下角的位置,拼接完成后这将是root的最右下角
        if (left!=NULL) 
        {
            left->right=root->right;//将右子树接到左子树最下面
            root->right=root->left;//将整棵左子树接到右子树的位置
            root->left=NULL;
         }
        if (right!=NULL) return right;//右子树存在最右下角的位置则优先返回这个位置(因为这个位置将是最右的)
        if (left!=NULL) return left;//如果没有右子树的右下角,则左子树的右下角是最后一个位置
        return root;//都没有就返回根
    }
};


 

猜你喜欢

转载自blog.csdn.net/musechipin/article/details/86472101