代码随想录算法训练营第二十天|654.最大二叉树、617.合并二叉树、# 700.二叉搜索树中的搜索、98.验证二叉搜索树

654.最大二叉树

我的版本

  • 类似于从前序后序构造二叉树
  • 关键点类似于二分查找
    • 去寻找那个区间不变量,我用的这个算是左开右闭的区间
class Solution1 {
  //每次构造新数组,占用空间大
 public:
	TreeNode *constructMaximumBinaryTree(vector<int> &nums) {
		if (nums.size() == 0)return nullptr;
		int maxIndex = 0;
		int maxValue = INT_MIN;
		for (int i = 0; i < nums.size(); ++i) {
			if (nums[i] > maxValue) {
				maxValue = nums[i];
				maxIndex = i;
			}
		}
		TreeNode *root = new TreeNode(maxValue);

		vector<int> leftnums(nums.begin(), nums.begin() + maxIndex);
		vector<int> rightnums(nums.begin() + maxIndex + 1, nums.end());
		root->left = constructMaximumBinaryTree(leftnums);
		root->right = constructMaximumBinaryTree(rightnums);
		return root;
	}
};

class Solution2 {
  //函数参数传入左右区间索引,一直使用nums数组,提高性能
 public:
	TreeNode *traversal(const vector<int> &nums, int leftIndex, int rightInndex) {
		if (leftIndex >= rightInndex) return nullptr;
		int maxIndex = 0;
		int maxValue = INT_MIN;
		for (int i = leftIndex; i < rightInndex; ++i) {
			if (nums[i] > maxValue) {
				maxValue = nums[i];
				maxIndex = i;
			}
		}
		TreeNode *root = new TreeNode(maxValue);

		int left_leftIndex = leftIndex;
		int left_rightIndex = maxIndex;
		int right_leftIndex = maxIndex + 1;
		int right_rightIndex = rightInndex;

		root->left = traversal(nums, left_leftIndex, left_rightIndex);
		root->right = traversal(nums, right_leftIndex, right_rightIndex);
		return root;

	}
	TreeNode *constructMaximumBinaryTree(vector<int> &nums) {
		//还是说要注意区间,我这里用的是左闭右开
		return traversal(nums, 0, nums.size());
	}
};

代码随想录

意思一样

617.合并二叉树

我的版本

  • 有点类似于对称二叉树,都是操作两个二叉树
  • 关键点就是遍历到某一个节点时
    • 如果两个树结构对不上了,直接返回有的那个子树补上来即可
  • 如果两个节点都存在,直接相加就行
class Solution {
 public:
	TreeNode *mergeTrees(TreeNode *root1, TreeNode *root2) {
		if (root1 == nullptr) return root2;
		if (root2 == nullptr) return root1;
		root1->val += root2->val;

		root1->left = mergeTrees(root1->left, root2->left);
		root1->right = mergeTrees(root1->right, root2->right);
		return root1;
	}
};

代码随想录

  • 递归方法是一样的

迭代方法

  • 使用队列模拟的进行层序遍历,
class Solution {
public:
    TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
        if (t1 == NULL) return t2;
        if (t2 == NULL) return t1;
        queue<TreeNode*> que;
        que.push(t1);
        que.push(t2);
        while(!que.empty()) {
            TreeNode* node1 = que.front(); que.pop();
            TreeNode* node2 = que.front(); que.pop();
            // 此时两个节点一定不为空,val相加
            node1->val += node2->val;

            // 如果两棵树左节点都不为空,加入队列
            if (node1->left != NULL && node2->left != NULL) {
                que.push(node1->left);
                que.push(node2->left);
            }
            // 如果两棵树右节点都不为空,加入队列
            if (node1->right != NULL && node2->right != NULL) {
                que.push(node1->right);
                que.push(node2->right);
            }

            // 当t1的左节点 为空 t2左节点不为空,就赋值过去
            if (node1->left == NULL && node2->left != NULL) {
                node1->left = node2->left;
            }
            // 当t1的右节点 为空 t2右节点不为空,就赋值过去
            if (node1->right == NULL && node2->right != NULL) {
                node1->right = node2->right;
            }
        }
        return t1;
    }
};

700.二叉搜索树中的搜索

我的版本

  • 直接递归,如果空就返回null
  • 找到了返回当前root
  • 大了的话去左子树找,小了同理
class Solution {
 public:
	TreeNode *searchBST(TreeNode *root, int val) {
		if (root == nullptr) return nullptr;
		if (root->val == val) return root;
		if (root->val > val) return searchBST(root->left, val);
		if (root->val < val) return searchBST(root->right, val);
		return nullptr;
	}
};

代码随想录

多了一个迭代的方法:

  • 由于是二叉搜索树,直接按照大了向左,小了向右。一直走就好了
class Solution {
public:
    TreeNode* searchBST(TreeNode* root, int val) {
        while (root != NULL) {
            if (root->val > val) root = root->left;
            else if (root->val < val) root = root->right;
            else return root;
        }
        return NULL;
    }
};

98.验证二叉搜索树

我的版本

  • 因为是二叉搜索树嘛,直接中序遍历得到的应该是一个递增数组
  • 检查这个数组是不是递增的就好
class Solution {
 public:
	void traversal(TreeNode *root, vector<int> &nums) {
		if (root == nullptr) return;
		traversal(root->left, nums);
		nums.push_back(root->val);
		traversal(root->right, nums);
	}
	bool isValidBST(TreeNode *root) {
		vector<int> nums;
		traversal(root, nums);
		int temp = nums[0];
		for (auto iter = nums.begin() + 1; iter != nums.end(); ++iter) {
			//注意这里是小于等于 不是小于
			if (*iter <= temp)
				return false;
			temp = *iter;
		}
		return true;
	}
};

代码随想录

递归

除了获得数组之外,给出了递归的方法:

代码随想录 (programmercarl.com)

  • 不能淡出的比较左节点小于中间节点就行,因为左节点下面的节点可能不合法
  • 要比较左子树所有节点小于中间节点,右子树所有节点大于中间节点
  • 注意测试样例中有INT_MIN,所以使用一个longlong
class Solution {
public:
    long long maxVal = LONG_MIN; // 因为后台测试数据中有int最小值
    bool isValidBST(TreeNode* root) {
        if (root == NULL) return true;

        bool left = isValidBST(root->left);
        // 中序遍历,验证遍历的元素是不是从小到大
        if (maxVal < root->val) maxVal = root->val;
        else return false;
        bool right = isValidBST(root->right);

        return left && right;
    }
};

迭代

class Solution {
public:
    bool isValidBST(TreeNode* root) {
        stack<TreeNode*> st;
        TreeNode* cur = root;
        TreeNode* pre = NULL; // 记录前一个节点
        while (cur != NULL || !st.empty()) {
            if (cur != NULL) {
                st.push(cur);
                cur = cur->left;                // 左
            } else {
                cur = st.top();                 // 中
                st.pop();
                if (pre != NULL && cur->val <= pre->val)
                return false;
                pre = cur; //保存前一个访问的结点

                cur = cur->right;               // 右
            }
        }
        return true;
    }
};

day20结束

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值