随想录一刷Day19——二叉树

Day19_二叉树

19. 最大二叉树

654. 最大二叉树
思路:

首先 O ( n ) O(n) O(n) 找到数组中最大的元素下标,以该值为根节点,然后递归构建左右子树
递归的返回值是当前构造的节点

写法一: 将原函数改为递归函数

class Solution {
public:
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        TreeNode *root = new TreeNode(0);
        int nums_size = nums.size();
        if (nums_size == 1) { // 叶结点
            root->val = nums[0];
            return root;
        }

        // 寻找当前数组中的最大值
        int MaxIndex = 0;
        for (int i = 1; i < nums_size; i++) {
            if (nums[MaxIndex] < nums[i]) MaxIndex = i;
        }
        root->val = nums[MaxIndex];

        // 构建左子树
        if (MaxIndex > 0) {
            vector<int> left_vec(nums.begin(), nums.begin() + MaxIndex);
            root->left = constructMaximumBinaryTree(left_vec);
        }

        // 构建右子树
        if (MaxIndex < nums_size - 1) {
            vector<int> right_vec(nums.begin() + MaxIndex + 1, nums.end());
            root->right = constructMaximumBinaryTree(right_vec);
        }

        // 递归返回值为当前子节点
        return root;
    }
};

写法二: 重新构造递归函数
由于写法一要多次使用迭代器构造新的数组,造成时间浪费,这里改用原数组,每次给出左右区间的下标。

class Solution {
private:
    TreeNode* Traversal(vector<int>& nums, int left, int right) {
        // 寻找最大值下标
        int MaxIndex = left;
        for (int i = left + 1; i < right; i++) {
            if (nums[MaxIndex] < nums[i]) MaxIndex = i;
        }
        TreeNode* root = new TreeNode(nums[MaxIndex]);

        // 构造左子树
        if (MaxIndex > left) {
            root->left = Traversal(nums, left, MaxIndex);
        }

        // 构造右子树
        if (MaxIndex < right - 1) {
            root->right = Traversal(nums, MaxIndex + 1, right);
        }

        // 返回当前节点
        return root;
    }

public:
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        return Traversal(nums, 0, nums.size());
    }
};

21. 合并二叉树

617. 合并二叉树
思路:

同时遍历两棵树,分三种情况:

  1. 两棵树都空了,说明当前分支合并结束,返回
  2. 两棵树都不空,合并时重叠,将两节点的值相加后继续合并
  3. 一棵树空另一棵不空,合并时直接选择不空的树,结束当前分支的合并

写法一:

class Solution {

public:
    TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
        TreeNode* root = new TreeNode(0);

        // 遍历结束
        if (root1 == NULL && root2 == NULL) return NULL;

        // 重叠节点
        else if (root1 != NULL && root2 != NULL ) {
            root->val = root1->val + root2->val;
            root->left = mergeTrees(root1->left, root2->left);
            root->right = mergeTrees(root1->right, root2->right);
        }

        // 不重叠的节点
        else {
            if (root1 == NULL) root = root2;
            else root = root1;
            return root;
        }
        return root;
    }
};

写法二:
对比之下,卡哥的写法真是简洁明了。
合并两棵树既可以用前中后序遍历均可,下面使用先序遍历。

class Solution {

public:
    TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
        if (root1 == NULL) return root2;
        if (root2 == NULL) return root1;

        TreeNode* root = new TreeNode(0);
        root->val = root1->val + root2->val; // 前序
        root->left = mergeTrees(root1->left, root2->left);
        // 中序
        root->right = mergeTrees(root1->right, root2->right);
        // 后续

        return root;
    }
};

写法三:
迭代法:将 root2 合并到 root1

class Solution {

public:
    TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
        if (root1 == NULL) return root2;
        if (root2 == NULL) return root1;

        queue<TreeNode*> que;
        que.push(root1);
        que.push(root2);

        while (!que.empty()) {
            TreeNode* node1 = que.front(); que.pop();
            TreeNode* node2 = que.front(); que.pop();
            // 两个节点一定都不为空
            node1->val += node2->val;

            // 左子节点重叠
            if (node1->left && node2->left) {
                que.push(node1->left);
                que.push(node2->left);
            }

            // 右子节点重叠
            if (node1->right && node2->right) {
                que.push(node1->right);
                que.push(node2->right);
            }

            // node1->left 为空, node2->left 不为空
            if (node1->left == NULL && node2->left)
                node1->left = node2->left;

            // node->right 为空,node2->right 不为空
            if (node1->right == NULL && node2->right) 
                node1->right = node2->right;

            // 均为空
        }

        return root1;
    }
};

22. 二叉搜索树中的搜索

700. 二叉搜索树中的搜索
思路:

二叉搜索树,比根节点大去右子树查,比根节点小去左子树查,找到结果返回当前节点(子树),找到叶结点也没找到 val 则不在 BST 中

class Solution {
public:
    TreeNode* searchBST(TreeNode* root, int val) {
        if (root == NULL) return NULL;
        TreeNode* ans = root;

        if (root->val > val) ans = searchBST(root->left, val);
        else if (root->val < val) ans = searchBST(root->right, val);
        
        return ans;
    }
};

迭代法:
这个迭代法太感人了,很难再有这么简单的迭代法了

class Solution {
public:
    TreeNode* searchBST(TreeNode* root, int val) {
        while (root) {
            if (root->val > val) root = root->left;
            else if (root->val < val) root = root->right;
            else break;
        }
        return root;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值