654.最大二叉树
链接:. - 力扣(LeetCode)
题目描述:
给定一个不重复的整数数组
nums
。 最大二叉树 可以用下面的算法从nums
递归地构建:
- 创建一个根节点,其值为
nums
中的最大值。- 递归地在最大值 左边 的 子数组前缀上 构建左子树。
- 递归地在最大值 右边 的 子数组后缀上 构建右子树。
返回
nums
构建的 最大二叉树 。示例 1:
输入:nums = [3,2,1,6,0,5] 输出:[6,3,5,null,2,0,null,null,1] 解释:递归调用如下所示: - [3,2,1,6,0,5] 中的最大值是 6 ,左边部分是 [3,2,1] ,右边部分是 [0,5] 。- [3,2,1] 中的最大值是 3 ,左边部分是 [] ,右边部分是 [2,1] 。- 空数组,无子节点。- [2,1] 中的最大值是 2 ,左边部分是 [] ,右边部分是 [1] 。- 空数组,无子节点。- 只有一个元素,所以子节点是一个值为 1 的节点。- [0,5] 中的最大值是 5 ,左边部分是 [0] ,右边部分是 [] 。- 只有一个元素,所以子节点是一个值为 0 的节点。- 空数组,无子节点。示例 2:
输入:nums = [3,2,1] 输出:[3,null,2,null,1]提示:
1 <= nums.length <= 1000
0 <= nums[i] <= 1000
nums
中的所有整数 互不相同
思路:
使用前序遍历的方式创建,先在数组中找到根节点的位置和值,定义一个节点用来存储根节点的信息,根据根节点来对数组进行分割
使用递归进行实现:
1.先确定函数的参数和返回值,函数应该返回创建的节点,参数应该是数组,已经左右子树的区间范围
2.确定函数的终止条件,当遍历到叶子节点,即数组的长度为1,则赋值之后就该返回
3.确定单层递归逻辑,需要想先找到根节点的值和位置,分割数组创造左右子树
代码实现:
/*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/ struct TreeNode *create(int *nums, int lindex, int rindex) {//左子树的范围在数组中比右子树大if (lindex >= rindex)return NULL;//找出根节点的位置int max_val = nums[lindex]; // 将 max_val 初始化为第一个元素的值int max_val_index = lindex;for(int i = lindex + 1 ; i < rindex; i++){if(nums[i] > max_val){max_val = nums[i];max_val_index = i;}}struct TreeNode *node = (struct TreeNode *)malloc(sizeof(struct TreeNode));node->val = max_val;node->left = create(nums, lindex , max_val_index);node->right = create(nums, max_val_index + 1 ,rindex);return node; }struct TreeNode* constructMaximumBinaryTree(int* nums, int numsSize) {return create(nums, 0 , numsSize); }
注意:max_val初始化应该为数组的第一个元素,不能初始化为0,否则会导致根节点的判断出错
617.合并二叉树
链接:. - 力扣(LeetCode)
题目描述:
给你两棵二叉树:
root1
和root2
。想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新二叉树。合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 null 的节点将直接作为新二叉树的节点。
返回合并后的二叉树。
注意: 合并过程必须从两个树的根节点开始。
示例 1:
输入:root1 = [1,3,2,5], root2 = [2,1,3,null,4,null,7] 输出:[3,4,5,5,4,null,7]示例 2:
输入:root1 = [1], root2 = [1,2] 输出:[2,2]提示:
- 两棵树中的节点数目在范围
[0, 2000]
内-104 <= Node.val <= 104
思路:
使用递归函数来进行解决,因为要合并两颗二叉树,因此我们需要同时遍历两颗二叉树,并且不开劈新的内存空间,而是将两个合并后的结果放在其中一颗树里
1.确定函数的参数和返回值:因为同时遍历两颗二叉树,因此参数应该传入两个二叉树的根节点
2.确定递归的终止条件:当其中一颗二叉树为空,则返回另外一颗二叉树
3.确定单层递归逻辑:将两颗二叉树合并到一颗树上,使用前中后序遍历都可以
代码实现:
/*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/ struct TreeNode* mergeTrees(struct TreeNode* root1, struct TreeNode* root2) {if(!root1 && root2)return root2;else if(root1 && !root2)return root1;else if(!root1 && !root2)return NULL;root1->val += root2->val; //中root1->left = mergeTrees(root1->left,root2->left); //左root1->right = mergeTrees(root1->right,root2->right); //右return root1; }
700.二叉搜索树中的搜索
链接:. - 力扣(LeetCode)
题目描述:
给定二叉搜索树(BST)的根节点
root
和一个整数值val
。你需要在 BST 中找到节点值等于
val
的节点。 返回以该节点为根的子树。 如果节点不存在,则返回null
。示例 1:
输入:root = [4,2,7,1,3], val = 2 输出:[2,1,3]示例 2:
输入:root = [4,2,7,1,3], val = 5 输出:[]提示:
- 树中节点数在
[1, 5000]
范围内1 <= Node.val <= 107
root
是二叉搜索树1 <= val <= 107
关于二叉搜索树
1.对于BST中的每个节点,其左子树中的所有节点的值都小于该节点的值,而其右子树中的所有节点的值都大于该节点的值。这个性质保证了BST的有序性,使得对其进行搜索、插入和删除等操作更加高效
2.BST中不存在两个相同值的节点。每个节点的值都是唯一的
3.BST的左子树和右子树也分别是BST
4.对BST进行中序遍历,可以得到一个递增的有序序列
递归思路:
根据二叉搜索树的性质,可以有规律的去查找,使用递归函数来实现
1.确定函数的参数和返回值,参数应该要传入二叉搜索树的根节点和要查找的值,因为要返回值相等的子树,因此返回值也是一个节点
2.确定递归终止条件,当我们查找到相同的值,或者当节点为空时,我们就返回这个节点
3.确定单层递归逻辑,当该节点的值小于我们要查找的值,我们就去其右子树查找,当该节点的值大于我们要去查找的值,我们就去其左子树查找,如果没有找到,则返回空
提示:
如果需要搜索整颗二叉树,那么递归函数就不要返回值,如果要搜索其中一条符合条件的路径,递归函数就需要返回值,因为遇到符合条件的路径了就要及时返回
代码实现:
/*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/ struct TreeNode* searchBST(struct TreeNode* root, int val) {if(root == NULL || root->val == val)return root;if(root->val > val)return searchBST(root->left, val);if(root->val < val)return searchBST(root->right, val);return NULL; }
迭代法实现:
与递归的思路一样,根据二叉搜索树的性质来查找
代码实现:
/*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/ struct TreeNode* searchBST(struct TreeNode* root, int val) {while(root != NULL){if(root->val > val)root = root->left;else if(root->val < val)root = root->right;else if(root->val == val)return root;}return NULL; }
98.验证二叉搜索树
链接:. - 力扣(LeetCode)
题目描述:
给你一个二叉树的根节点
root
,判断其是否是一个有效的二叉搜索树。有效 二叉搜索树定义如下:
- 节点的左
子树
只包含 小于 当前节点的数。- 节点的右子树只包含 大于 当前节点的数。
- 所有左子树和右子树自身必须也是二叉搜索树。
示例 1:
输入:root = [2,1,3] 输出:true示例 2:
输入:root = [5,1,4,null,null,3,6] 输出:false 解释:根节点的值是 5 ,但是右子节点的值是 4 。提示:
- 树中节点数目范围在
[1, 104]
内-231 <= Node.val <= 231 - 1
思路:
根据二叉搜索树的性质可知,其左子树中的所有节点的值都小于该节点的值,而其右子树中的所有节点的值都大于该节点的值,对BST进行中序遍历,可以得到一个递增的有序序列
因此,我们使用中序遍历的思想来进行解决,将所有的节点元素都存入数组中,最后判断我们的数组是否是递增的即可
递归实现:
1.确定函数的参数和返回值,因为要将二叉树节点都存入数组,因此传入的参数应该为二叉树的根节点,要存入的数组,注意还需要一个计数器,计算节点个数,不需要返回值
2.确定函数的终止条件,当二叉树为空,则退出
3.确定单层的递归逻辑,使用中序遍历,将二叉树的节点都存入数组中
代码:
/*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/ //中序遍历存入数组 void fc(struct TreeNode *root, int *nums, int *cout) {if(!root)return;fc(root->left, nums,cout);nums[(*cout)++] = root->val;fc(root->right, nums,cout); }bool isValidBST(struct TreeNode* root) {int *nums = (int *)malloc(sizeof(int)*10000);int cout = 0;fc(root,nums, &cout);for(int i = 0; i < cout-1; i++){if(nums[i] >= nums[i+1])return false;}return true; }
易错点:
不能进行这样简单的判断,这样判断的至少当前节点的顺序,而我们要保证的是整个左子树小于根节点小于整个右子树