LeetCode算法练习——树(三)

LeetCode501. 二叉搜索树中的众数

给定一个有相同值的二叉搜索树(BST),找出 BST 中的所有众数(出现频率最高的元素)。

class Solution
{
public:
    vector<int> findMode(TreeNode *root){
        vector<int> res;    // 要返回的结果
        // max_count: 结果元素的出现次数
        // cur_count: 当前元素的出现次数
        // ret_count: 结果 vector 的长度
        int max_count = 0, cur_count = 0, res_count = 0;
        // pre: 上一个访问的结点
        TreeNode *pre = nullptr;
        // 第一次中序遍历,发现有多少个众数
        inorder(root, pre, res, res_count, max_count, cur_count);
        // 第二次中序遍历
        res.resize(res_count);
        cur_count = 0;
        res_count = 0;
        pre = nullptr;
        inorder(root, pre, res, res_count, max_count, cur_count);
        return res;
    }
    void inorder(TreeNode *root, TreeNode *&pre, vector<int> &res, int &res_count, int &max_count, int &cur_count){
        if (!root)
            return;
        inorder(root->left, pre, res, res_count, max_count, cur_count);
        if (pre && pre->val == root->val)
            cur_count++;
        else    // 否则,cur_count 重新计数
            cur_count = 1;
        if (cur_count > max_count) {
            max_count = cur_count;
            res_count = 1;
        }
        else if (cur_count == max_count) {
            if (res.size()) // 注意这里,第一次遍历时,这里的if不会执行
                res[res_count] = root->val;
            res_count++;
        }
        pre = root;
        inorder(root->right, pre, res, res_count, max_count, cur_count);
    }
};

LeetCode572. 另一个树的子树

给定两个非空二叉树 s 和 t,检验 s 中是否包含和 t 具有相同结构和节点值的子树。s 的一个子树包括 s 的一个节点和这个节点的所有子孙。s 也可以看做它自身的一棵子树。

class Solution {
public:
    bool dfs(TreeNode *o, TreeNode *t) {
        if (!o && !t) return true;
        //判断二者节点是否相等,数值是否相等
        if ((o && !t) || (!o && t) || (o->val != t->val)) return false;
        return dfs(o->left, t->left) && dfs(o->right, t->right);
    }
    bool isSubtree(TreeNode *s, TreeNode *t) {
        if((s == nullptr && t != nullptr) || (s != nullptr && t == nullptr )) 
            return false;
        else if(s == nullptr && t == nullptr) 
            return true;
        else
            return dfs(s, t) || isSubtree(s->left, t) || isSubtree(s->right, t); 
    }
};

LeetCode671. 二叉树中第二小的节点

给定一个非空特殊的二叉树,每个节点都是正数,并且每个节点的子节点数量只能为 2 或 0。如果一个节点有两个子节点的话,那么该节点的值等于两个子节点中较小的一个。给出这样的一个二叉树,你需要输出所有节点中的第二小的值。如果第二小的值不存在的话,输出 -1 。

class Solution {
public:
    int findSecondMinimumValue(TreeNode* root) {
        if(!root || !root->left || !root->right) return -1;//空节点或不满足题意
        int left = root->left->val, right = root->right->val;
        //若根节点和左节点值相同,则递归找左子树的第二小节点
        if(root->val == root->left->val) left = findSecondMinimumValue(root->left);
        //若根节点和右节点值相同,则递归找右子树的第二小节点
        if(root->val == root->right->val) right = findSecondMinimumValue(root->right);
        //若根节点等于左右子树的第二小节点返回-1
        if(root->val == left && root->val == right) return -1;
        //根据当前的根、左右节点的值继续判断
        int min_lr = min(left, right);
        if(root->val < min_lr) return min_lr;       //根节点小于最小值,返回最小值
        else return max(left, right);               //根节点等于最小值,返回最大值
    }
};

LeetCode617. 合并二叉树

给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点便会重叠。你需要将他们合并为一个新的二叉树。合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值,否则不为 NULL 的节点将直接作为新二叉树的节点。

class Solution {
public:
    TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
        TreeNode* root;                                     //根节点
        if(t1 == nullptr && t2 == nullptr) return nullptr;  //全为空创建完毕 返回空节点
        if(t1 != nullptr && t2 != nullptr){                 //t1 t2 都不是空间点
            root = new TreeNode(t1->val + t2->val);
            root->left = mergeTrees(t1->left, t2->left);
            root->right = mergeTrees(t1->right, t2->right);
        }
        else if(t1 != nullptr){                             //t2 空
            root = new TreeNode(t1->val);
            root->left = mergeTrees(t1->left, t2);
            root->right = mergeTrees(t1->right, t2);
        }
        else if(t2 != nullptr){                             // t1 空
            root = new TreeNode(t2->val);
            root->left = mergeTrees(t1, t2->left);
            root->right = mergeTrees(t1, t2->right);
        }
        return root;                                        //返回根节点
    }
};

LeetCode606. 根据二叉树创建字符串

你需要采用前序遍历的方式,将一个二叉树转换成一个由括号和整数组成的字符串。空节点则用一对空括号 "()" 表示。而且你需要省略所有不影响字符串与原始二叉树之间的一对一映射关系的空括号对。

输入: 二叉树: [1,2,3,4]
       1
     /   \
    2     3
   /    
  4     

输出: "1(2(4))(3)"
class Solution {
public:
    void dfs(TreeNode* t, string & str){
        if(t == NULL) return;
        str += to_string(t->val);
        if(t->left || t->right){
            str += "(";
            dfs(t->left, str);
            str += ")";
        }
        if(t->right){
            str += "(";
            dfs(t->right, str);
            str += ")";
        }
    }
    
    string tree2str(TreeNode* t) {
        string res = "";
        dfs(t, res);
        return res;
    }
};

LeetCode543. 二叉树的直径

给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。

class Solution {
public:
    int length = 0;
    int diameterOfBinaryTree(TreeNode* root) {
        depth(root);
        return length;
    }

    int depth(TreeNode* root) {
        if (!root) return 0;
        int left = depth(root->left);
        int right = depth(root->right);
        length = max(length, left + right);
        return max(left, right) + 1;
    }
};

LeetCode669. 修剪二叉搜索树

给定一个二叉搜索树,同时给定最小边界L 和最大边界 R。通过修剪二叉搜索树,使得所有节点的值在[L, R]中 (R>=L) 。你可能需要改变树的根节点,所以结果应当返回修剪好的二叉搜索树的新的根节点。

class Solution {
public:
    TreeNode* trimBST(TreeNode* root, int L, int R) {
        if (root == nullptr) return nullptr;
        //root->val < L,去遍历节点右子树
        if (root->val < L) return trimBST(root->right, L, R);
        //root->val > R,去遍历节点左子树
        if (root->val > R) return trimBST(root->left, L, R);
        root->left = trimBST(root->left, L, R);
        root->right = trimBST(root->right, L, R);
        return root;
    }
};

LeetCode112. 路径总和

给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。

class Solution {
public:
    bool hasPathSum(TreeNode* root, int sum) {
        if(root == NULL)    return false;
        sum -= root->val;
        if(root->left == NULL && root->right == NULL)   return sum == 0;
        return hasPathSum(root->left, sum) || hasPathSum(root->right, sum);
    }
};

LeetCode687. 最长同值路径

给定一个二叉树,找到最长的路径,这个路径中的每个节点具有相同值。 这条路径可以经过也可以不经过根节点。

class Solution {
public:
    int longestUnivaluePath(TreeNode* root) {
        int res = 0;
        dfs(root, res);
        return res;
    }
    int dfs(TreeNode* root, int& sum){
        if(root == NULL)    return 0;
        int left = dfs(root->left, sum);
        int right = dfs(root->right, sum);
        left = (root->left != NULL && root->val == root->left->val) ? left + 1 : 0;
        right = (root->right != NULL && root->val == root->right->val) ? right + 1 : 0;
        sum = max(sum, left + right);
        return max(left, right);
    }
};

LeetCode783. 二叉搜索树节点最小距离

给定一个二叉搜索树的根节点 root,返回树中任意两节点的差的最小值。

class Solution {
public:
    int minDiffInBST(TreeNode* root) {
        TreeNode* p = root->left ? root->left : root->right;
        int min = abs(root->val - p->val);
        int pre = 0;            //记录中序遍历的前一个的值
        bool flag = false;      //为false时 还未遍历到第一个中序节点 为true时 pre已经有值
        inorder(root, pre, flag, min);
        return min; 
    }
    void inorder(TreeNode* root, int& pre, bool& flag, int& minVal){
        if(!root)   return ;
        inorder(root->left, pre, flag, minVal);
        if(flag == false){
            pre = root->val;
            flag = true;
        }
        else{
            minVal = min(abs(pre - root->val), minVal);
            pre = root->val;
        }
        inorder(root->right, pre, flag, minVal);
    }
};

LeetCode1022. 从根到叶的二进制数之和

给出一棵二叉树,其上每个结点的值都是 0 或 1 。每一条从根到叶的路径都代表一个从最高有效位开始的二进制数。例如,如果路径为 0 -> 1 -> 1 -> 0 -> 1,那么它表示二进制数 01101,也就是 13 。对树上的每一片叶子,我们都要找出从根到该叶子的路径所表示的数字。以 10^9 + 7 为模,返回这些数字之和。

class Solution {
public:
    long M = 1e9 + 7;
    void dfs(TreeNode* root, long nums, long& res) {
        if (root == NULL) return;
        nums = (nums << 1) | root->val;
        if (root->left == NULL && root->right == NULL) {
            res += nums;
            res %= M;
            return;
        }
        dfs(root->left, nums, res);
        dfs(root->right, nums, res);
    }
    int sumRootToLeaf(TreeNode* root) {
        long res = 0;
        long nums = 0;
        dfs(root, nums, res);
        return res;
    }
};

LeetCode993. 二叉树的堂兄弟节点

在二叉树中,根节点位于深度 0 处,每个深度为 k 的节点的子节点位于深度 k+1 处。如果二叉树的两个节点深度相同,但父节点不同,则它们是一对堂兄弟节点。我们给出了具有唯一值的二叉树的根节点 root,以及树中两个不同节点的值 x 和 y。只有与值 x 和 y 对应的节点是堂兄弟节点时,才返回 true。否则,返回 false。

class Solution {
public:
    bool isCousins(TreeNode* root, int x, int y) {
        if(!root)   return false;
        queue<TreeNode*> q;
        q.push(root);
        while(!q.empty()){
            int length = q.size();
            bool xExisit = false;
            bool yExisit = false;
            for(int i = 0; i < length; i++){      
                //同层添加,注意这里是length不是q.size(),因为q.size()在循环中会动态变化
                auto node = q.front();
                q.pop();
                if(node->val == x)  xExisit = true;
                if(node->val == y)  yExisit = true;
                if (node->left && node->right){
                    //两个孩子节点同属于一个父节点
                    if(node->left->val == x && node->right->val == y)
                        return false;
                    if(node->left->val == y && node->right->val == x)
                        return false;
                }
                if(node->left)   q.push(node->left);
                if(node->right)  q.push(node->right);
            }
            if(xExisit && yExisit)  return true;
        }
        return false;
    }
};

 

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页