113.路径综合2(多理解理解)
int** ret;
int retSize;
int* retColSize;
int* path;
int pathSize;
void dfs(struct TreeNode* root, int targetSum) {
if (root == NULL) {
return;
}
path[pathSize++] = root->val;//加入预备输出的路径
targetSum -= root->val;
if (root->left == NULL && root->right == NULL && targetSum == 0) {
//到叶子结点,且targetsum刚好降为0,符合题意,输出路径!
int* tmp = malloc(sizeof(int) * pathSize);
memcpy(tmp, path, sizeof(int) * pathSize);
ret[retSize] = tmp;
retColSize[retSize++] = pathSize;
}
dfs(root->left, targetSum);
dfs(root->right, targetSum);
pathSize--;//表示回退了,也就是找完left 和 right都没有符合题意的情况,所以回退到上一个结点
}
int** pathSum(struct TreeNode* root, int targetSum, int* returnSize, int** returnColumnSizes) {
ret = malloc(sizeof(int*) * 2001);
retColSize = malloc(sizeof(int) * 2001);
path = malloc(sizeof(int) * 2001);
retSize = pathSize = 0;
dfs(root, targetSum);
*returnColumnSizes = retColSize;
*returnSize = retSize;
return ret;
}
654.最大二叉树
给定一个不含重复元素的整数数组。一个以此数组构建的最大二叉树定义如下:
- 二叉树的根是数组中的最大元素。
- 左子树是通过数组中最大值左边部分构造出的最大二叉树。
- 右子树是通过数组中最大值右边部分构造出的最大二叉树。
通过给定的数组构建最大二叉树,并且输出这个树的根节点。
注意**:
用指针遍历数组(char*,int*)
int*p=nums;此时*p是int,指向nums[0]
for(int *p=nums;p< nums+size;p++) 用int*+x,表示指针向右移动x步
int findmax(int* nums, int numsSize){//返回第几位是最大值
int maxnumber=INT_MIN;
int *maxp=nums;
int *p=nums;
for(p=nums;p<nums+numsSize;p++){
if(*p>maxnumber){
maxnumber=*p;
maxp=p;
}
}
return (maxp-nums);
}
struct TreeNode* constructMaximumBinaryTree(int* nums, int numsSize) {
if (nums==NULL) return NULL;
if(numsSize<=0) return NULL;
struct TreeNode* b=(struct TreeNode* )malloc(sizeof(struct TreeNode));
int i=findmax(nums, numsSize);
b->val=nums[i];
b->left=constructMaximumBinaryTree(nums,i);
b->right=constructMaximumBinaryTree(nums+i+1,numsSize-i-1);
return b;
}
617.合并二叉树
给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点便会重叠。
你需要将他们合并为一个新的二叉树。合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值,否则不为 NULL 的节点将直接作为新二叉树的节点。
struct TreeNode* mergeTrees(struct TreeNode* root1, struct TreeNode* root2) {
if(root1==NULL && root2==NULL) return NULL;
//有一个是空的
if(root1!=NULL && root2==NULL) return root1;
else if(root1==NULL && root2!=NULL) return root2;
root1->val=root2->val+root1->val;//都不是空的,需要合并
root1->left=mergeTrees(root1->left,root2->left);
root1->right=mergeTrees(root1->right,root2->right);
return root1;
}
700.二叉搜索树中的搜索
给定二叉搜索树(BST)的根节点和一个值。 你需要在BST中找到节点值等于给定值的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 NULL。
二叉搜索树:
二叉搜索树是一个有序树:
- 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
- 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
- 它的左、右子树也分别为二叉搜索树
struct TreeNode* searchBST(struct TreeNode* root, int val) {
if(root==NULL) return NULL;
int x=root->val;
if(x==val) return root;
if(x>val) return searchBST(root->left,val);
else return searchBST(root->right,val);
}
98.验证二叉搜索树
给定一个二叉树,判断其是否是一个有效的二叉搜索树。
假设一个二叉搜索树具有如下特征:
- 节点的左子树只包含小于当前节点的数。
- 节点的右子树只包含大于当前节点的数。
- 所有左子树和右子树自身必须也是二叉搜索树。
注意:
二叉搜索树的性质:
不能单纯的比较左节点小于中间节点,右节点大于中间节点就完事了。
我们要比较的是 左子树所有节点小于中间节点,右子树所有节点大于中间节点。所以以上代码的判断逻辑是错误的。
1、用最大值、最小值来判断
int isBSTUtil(struct TreeNode* node, long long min, long long max)
{
/* 是一颗空树 */
if (node==NULL)
return 1;
/* 结点的值小于等于最小值,或者大于等于最大值都是不合理的,返回false */
if (node->val <= min || node->val >= max)
return 0;
/*否则递归地判断结点的左子树和右子树*/
return
isBSTUtil(node->left, min, node->val) &&
isBSTUtil(node->right, node->val, max);
}
2、中序遍历
要知道中序遍历下,输出的二叉搜索树节点的数值是有序序列。
有了这个特性,验证二叉搜索树,就相当于变成了判断一个序列是不是递增的了。