LeetNode:BM35-BM38

BM35-BM38

BM35 判断是不是完全二叉树

***解题思路:***
  1. 法一:层序遍历(以无右子树的节点为标记)
    • 不存在有右无左的节点
    • 标记节点(无右子树)后的节点都没有子节点
  2. 法二:层序遍历(遇到空节点后,则队列中其余元素全为空)
/**
 * struct TreeNode {
 *  int val;
 *  struct TreeNode *left;
 *  struct TreeNode *right;
 *  TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 * };
 */
#include <queue>

//法一:层序遍历
class Solution1 {
  public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param root TreeNode类
     * @return bool布尔型
     */

    /*  解题思路:层序遍历(以无右子树的节点为标记)
    **  1、不存在有右无左的节点
    **  2、标记节点(无右子树)后的节点都没有子节点
    */
    bool isCompleteTree(TreeNode* root) {
        // write code here
        if (root == nullptr || (!root->left && !root->right))return true;

        bool mask = false;
        queue<TreeNode*> qtn;
        qtn.push(root);

        while (!qtn.empty()) {
            TreeNode* tmp = qtn.front();
            qtn.pop();

            if (tmp->right && !tmp->left)return false;

            if (!mask) {
                if (tmp->left) qtn.push(tmp->left);

                if (!tmp->right)
                    mask = true;
                else
                    qtn.push(tmp->right);
            } else if (tmp->left || tmp->right)
                return false;
        }
        return true;
    }
};


class Solution {
  public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param root TreeNode类
     * @return bool布尔型
     */

    /*  解题思路:层序遍历
    */
    bool isCompleteTree(TreeNode* root) {
        // write code here
        if (root == nullptr)return true;

        TreeNode* star = root->left;
        int level = 0, lcnt = 0;
        queue<TreeNode*> qtn;
        qtn.emplace(root);
        while (!qtn.empty()) {
            TreeNode* tmp = qtn.front();
            qtn.pop();

            if (tmp == nullptr)break;
            qtn.push(tmp->left);
            qtn.push(tmp->right);
        }

        while(!qtn.empty()){
            TreeNode* tmp = qtn.front();
            qtn.pop();
            if (tmp != nullptr)return false;
        }

        return true;
    }
};

BM36 判断是不是平衡二叉树

***解题思路:***
  1. 法一:递归(左右子树的高度差是否大于1)
//法一:递归(左右子树的高度差是否大于1)
class Solution {
  public:

    bool flag = true;
    bool IsBalanced_Solution(TreeNode* pRoot) {
        if (pRoot == nullptr)return true;

        process(pRoot);
        return flag;
    }

    int process(TreeNode* node) {
        if (!flag || node == nullptr)return 0;

        int llevel = process(node->left);
        int rlevel = process(node->right);

        if (abs(llevel - rlevel) > 1) flag = false;

        return max(llevel, rlevel) + 1;
    }
};

BM37 二叉搜索树的最近公共祖先

***解题思路:***
  1. 法一:递归(最大值小于根节点,到左侧找;最小值大于根节点,到右侧找)
  2. 法二:法二:哈希表记录各节点和其父节点,set记录根节点到某节点的路径,再利用另一节点向上寻找公共祖先
/**
 * struct TreeNode {
 *  int val;
 *  struct TreeNode *left;
 *  struct TreeNode *right;
 *  TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 * };
 */

class Solution1 {
  public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param root TreeNode类
     * @param p int整型
     * @param q int整型
     * @return int整型
     */

    //法一:递归(最大值小于根节点,到左侧找;最小值大于根节点,到右侧找)
    int lowestCommonAncestor(TreeNode* root, int p, int q) {
        // write code here
        if (root == nullptr)return -1;
        if (p > q) {
            p = p ^ q;
            q = p ^ q;
            p = p ^ q;
        }

        if (root->val == p || root->val == q || (root->val > p && root->val < q))
            return root->val;
        if (root->val > q)
            return lowestCommonAncestor(root->left, p, q);

        return lowestCommonAncestor(root->right, p, q);
    }
};

//法二:哈希表记录各节点和其父节点,set记录根节点到某节点的路径,再利用另一节点向上寻找公共祖先

BM38 在二叉树中找到两个节点的最近公共祖先

***解题思路:***
  1. 法一:递归(1、左空右不空 或 右空左不空。2、左右都不空)
  2. 法二:子父节点配对,找到根节点到其中一个节点的路径set1,然后从另一个节点向上追溯,直至其祖先位于set1为止。(unordered_map + unordered_set)
  3. 法三:找到根节点到其中一个节点的路径stack,然后以栈各元素为根节点找寻另一个节点。(unordered_set + stack)
/**
 * struct TreeNode {
 *  int val;
 *  struct TreeNode *left;
 *  struct TreeNode *right;
 * };
 */


/**
*  法一:递归(1、左空右不空 或 右空左不空。2、左右都不空)
*/
class Solution {
  public:
    /**
     *
     * @param root TreeNode类
     * @param o1 int整型
     * @param o2 int整型
     * @return int整型
     */
    int lowestCommonAncestor(TreeNode* root, int o1, int o2) {
        // write code here
        TreeNode* node = Ancestor(root, o1, o2);
        return node->val;
    }

    TreeNode* Ancestor(TreeNode* root, int o1, int o2) {
        if (root == nullptr || root->val == o1 || root->val == o2)return root;

        TreeNode* lnode = Ancestor(root->left, o1, o2);
        TreeNode* rnode = Ancestor(root->right, o1, o2);
        if (lnode != nullptr && rnode != nullptr)return root;

        return lnode == nullptr ? rnode : lnode;
    }
};


/**
*  法二:unordered_map + unordered_set
*  解题思路:子父节点配对,找到根节点到其中一个节点的路径set1,然后从另一个节点向上追溯,直至其祖先位于set1为止。
*/
#include <fstream>
#include <functional>
#include <unordered_set>
class Solution2 {
  public:
    /**
     *
     * @param root TreeNode类
     * @param o1 int整型
     * @param o2 int整型
     * @return int整型
     */
    int lowestCommonAncestor(TreeNode* root, int o1, int o2) {
        // write code here

        unordered_map<TreeNode*, TreeNode*> ttmap;
        ttmap.emplace(root, root);
        pair<TreeNode*, TreeNode*> node12;
        process(root, ttmap, node12, o1, o2);

        unordered_set<TreeNode*> set1;
        TreeNode* cur = node12.first;
        while (cur != ttmap[cur]) {
            set1.emplace(cur);
            cur = ttmap[cur];
        }
        set1.emplace(root);

        cur = node12.second;
        while (set1.find(cur) == set1.end()) {
            cur = ttmap[cur];
        }
        return cur->val;
    }

    void process(TreeNode* node,
                 unordered_map<TreeNode*, TreeNode*>& ttmap, pair<TreeNode*, TreeNode*>& node12,
                 int o1,
                 int o2) {
        if (node == nullptr || (node12.first != nullptr &&
                                node12.second != nullptr))return;

        if (node->val == o1 || node->val == o2) {
            if (node12.first == nullptr)node12.first = node;
            else node12.second = node;
        }

        if (node->left)ttmap.emplace(node->left, node);
        if (node->right)ttmap.emplace(node->right, node);

        process(node->left, ttmap, node12, o1, o2);
        process(node->right, ttmap, node12, o1, o2);
    }

};


/**
*  法三:unordered_set + stack
*  解题思路:找到根节点到其中一个节点的路径stack,然后以栈各元素为根节点找寻另一个节点。
*/
class Solution3 {
  public:
    /**
     *
     * @param root TreeNode类
     * @param o1 int整型
     * @param o2 int整型
     * @return int整型
     */

    unordered_set<TreeNode*> checkset;
    stack<TreeNode*> spath;

    int lowestCommonAncestor(TreeNode* root, int o1, int o2) {
        // write code here
        process(root, o1, o2);

        int vtmp = spath.top()->val;
        int vsize = spath.size();
        int o = spath.top()->val == o1 ? o2 : o1;
        TreeNode* tmp;
        while (!spath.empty()) {
            tmp = spath.top();
            spath.pop();

            if (check(tmp, o))break;
            checkset.emplace(tmp);
        }
        return tmp->val;
    }

    bool process(TreeNode* node, int o1, int o2) {
        spath.emplace(node);

        if (node->val == o1 || node->val == o2) {
            return true;
        } else if (node->left || node->right) {
            if (node->left) {
                if (process(node->left, o1, o2))return true;
                spath.pop();
            }
            if (node->right) {
                if (process(node->right, o1, o2))return true;
                spath.pop();
            }
        }

        return false;
    }


    bool check(TreeNode* node, int o) {
        if (node == nullptr || checkset.find(node) != checkset.end())return false;

        if (node->val == o || check(node->left, o) || check(node->right, o))return true;

        return false;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值