一、513. 找树左下角的值
递归法:主要是需要理解深度怎么计算,以及最大深度的保存。
/**
1 递归方式
需要找到最大的深度 + 回溯
**/
// int maxdepth = INT_MIN;
// int result = 0;
void transDepth(struct TreeNode* cur, int depth, int* maxdepth, int* result)
{
if(cur->left == NULL && cur->right == NULL)
{
if(*maxdepth < depth)
{
*maxdepth = depth;
*result = cur->val;
printf("val = %d\n", *result);
}
return;
}
if(cur->left)
{
depth++;
transDepth(cur->left, depth, maxdepth, result);
depth--;
}
if(cur->right)
{
depth++;
transDepth(cur->right, depth, maxdepth, result);
depth--;
}
return;
}
int findBottomLeftValue(struct TreeNode* root) {
if(root == NULL)
return 0;
int maxdepth = INT_MIN;
int result = 0;
transDepth(root, 0, &maxdepth, &result);
return result;
}
二、112. 路径总和
本题需要理解到递归过程,什么时候需要返回值,另外,这种遍历所有或者在所有节点中搜索的题目,应该都需要回溯。
bool judge(struct TreeNode* root, int targetSum)
{
//递归过程
if(!root->left && !root->right && (targetSum) == 0)
return true;
if(!root->left && !root->right)
return false;
/**需要回溯**/
if(root->left)
{
targetSum -= root->left->val;
bool left_ret = judge(root->left, targetSum);
if(left_ret)
return true;
targetSum = targetSum + root->left->val;
}
if(root->right)
{
targetSum -= root->right->val;
bool right_ret = judge(root->right, targetSum);
if(right_ret)
return true;
targetSum = targetSum + root->right->val;
}
return false;
}
bool hasPathSum(struct TreeNode* root, int targetSum) {
if(root == NULL)
return false;//空树
return judge(root, targetSum - root->val);
}
用迭代法时候,填value值时候出现错误,是想去找top的上一个值,然后相加,结果就是在遍历过程,top可能会减到-1,然后再加回来,导致数组越界。
bool hasPathSum(struct TreeNode* root, int targetSum) {
if(root == NULL)
return false;//空树
//return judge(root, targetSum - root->val);
/**迭代法**/
//用两个数组来模拟栈
int top = -1;
struct TreeNode** NodeStk = (struct TreeNode**)malloc(sizeof(struct TreeNode*) * 5001);
int* nums = (int*)malloc(sizeof(int) * 5001);
/**入栈**/
NodeStk[++top] = root;
nums[top] = root->val;
/**遍历栈区**/
while(top > -1)
{
//出栈
struct TreeNode* curNode = NodeStk[top];
int curvalue = nums[top];
//printf("nums = %d\n", curvalue);
top--;
//判断
if(!curNode->left && !curNode->right && (curvalue == targetSum))
{
return true;
}
/**右子节点**/
int nums_pre_indx = top;
if(curNode->right)
{
nums[++top] = curvalue + curNode->right->val;
NodeStk[top] = curNode->right;
}
if(curNode->left)
{
nums[++top] = curvalue + curNode->left->val;
NodeStk[top] = curNode->left;
}
}
return false;
}
三、113 路径总和II
该题思路也是递归+回溯,根据代码随想录上面的思路,如下:
做该题使用遇到两个难点:
1)第一就是malloc时候,把returnsize和returncolSize放到递归函数里面,这样导致了参数过多,借鉴其他人的写法,可以使用全局变量,减少函数参数;
2)就是最后处理时候,应该memcpy到result里面。
int** result;
int* path;
int reSize ;
int* recolSize;
int path_idx;
void trans(struct TreeNode* curNode, int num)
{
if(!curNode->left && !curNode->right && (num == 0))
{
int* tmp = (int*)malloc(sizeof(int) * path_idx);
memcpy(tmp, path, sizeof(int) * (path_idx));
result[reSize] = tmp;
recolSize[(reSize)++] = path_idx;
return;
}
if(!curNode->left && !curNode->right)
{
return;
}
//printf("indx = %d\n", path_idx);
if(curNode->left)
{
path[(path_idx)++] = curNode->left->val;
num = num - curNode->left->val;
trans(curNode->left, num);
num = num + curNode->left->val;
(path_idx)--;
}
if(curNode->right)
{
path[(path_idx)++] = curNode->right->val;
num = num - curNode->right->val;
trans(curNode->right, num);
num = num + curNode->right->val;
(path_idx)--;
}
}
int** pathSum(struct TreeNode* root, int targetSum, int* returnSize, int** returnColumnSizes) {
//先使用路径总和1题目里面的迭代方式
if(root == NULL)
return NULL;//空树
reSize = 0;//代表有多少种路径
recolSize = (int*)calloc(2000, sizeof(int));//每一种路径里面 包含多少个节点
result = (int**)malloc(sizeof(int*) * 2000);
path = (int*) malloc(sizeof(int) * 5000);
path_idx = 0;
path[path_idx++] = root->val;
trans(root, targetSum - root->val);
*returnColumnSizes = recolSize;
*returnSize = reSize;
return result;
}
四、106.从中序与后序遍历序列构造二叉树
可以根据代码随想录的讲解思路进行解答,但是,在code过程还是遇到一些问题:
1 递归函数的参数设定:一开始就是思考的是就是用原函数,不用增加参数,但是这样递归时候,左区间和右区间并不能区分;
2 递归函数怎么实现:递归的时候,中序遍历的左区间和后序的左区间,得到左子树;右子树同理;
3 每一层申请新的root节点时候,初始化时候val和左右节点都需要初始化好,之前测试时候,left和right没有指向NULL,导致异常。
4 区间封闭原则需要注意!!
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
struct TreeNode* build(int* inorder, int inorderSize, int inorder_start, int inorder_end,
int* postorder, int postorderSize, int postorder_start, int postorder_end)
{
if (postorder_start == postorder_end)
return NULL;
//先找后序节点的最后一个,是头结点
int rootvalue = postorder[postorder_end -1];
struct TreeNode* root = (struct TreeNode*)malloc(sizeof(struct TreeNode));
root->val = rootvalue;//postorder[postorder_end -1];//这个是头结点
root->left = NULL;
root->right = NULL;//先初始化!!
if(postorder_end - postorder_start == 1)
{
return root;//只有一个节点的情况
}
int inorder_left_s = 0, inorder_left_e = 0;
int inorder_right_s =0, inorder_right_e = 0;
int postorder_left_s = 0, postorder_left_e = 0;
int postorder_right_s = 0, postorder_right_e = 0;
int middle_pos = 0;
/**分割中序数组:左右数组**/
for(middle_pos = inorder_start; middle_pos < inorder_end; middle_pos++)
{
if(inorder[middle_pos] == rootvalue)
{
break;
}
}
/**分开中序:左闭右开**/
inorder_left_s = inorder_start;
inorder_left_e = middle_pos;//
inorder_right_s = middle_pos + 1;
inorder_right_e = inorder_end;
/**分割后序数组:左闭右开**/
postorder_left_s = postorder_start;
postorder_left_e = postorder_start + middle_pos - inorder_start;
postorder_right_s = postorder_start + middle_pos - inorder_start;
postorder_right_e = postorder_end -1; //最后一个元素排除了
root->left = build(inorder, inorderSize, inorder_left_s, inorder_left_e, postorder, postorderSize, postorder_left_s, postorder_left_e);
root->right = build(inorder, inorderSize, inorder_right_s, inorder_right_e, postorder, postorderSize, postorder_right_s, postorder_right_e);
return root;
}
struct TreeNode* buildTree(int* inorder, int inorderSize, int* postorder, int postorderSize) {
//inorder是中序 postorder是后序
if(inorderSize == 0 || postorderSize == 0)
{
return NULL;//没有值
}
return build(inorder, inorderSize, 0, inorderSize, postorder, postorderSize, 0 , postorderSize);
}
五、105.从前序与中序遍历序列构造二叉树
需要注意以下几点:
1 前序遍历是首位置是头结点;
2 拆分前序遍历的左右区间时候,记得排除首位置元素,另外,起始位置也是改变了的。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
struct TreeNode* build(int* preorder, int preorderSize, int preorder_start, int preorder_end,
int* inorder, int inorderSize, int inorder_start, int inorder_end)
{
if (preorder_start == preorder_end)//切分到位置相等处 说明没有节点了
return NULL;
//先找前序节点的第一个,是头结点
int rootvalue = preorder[preorder_start];
struct TreeNode* root = (struct TreeNode*)malloc(sizeof(struct TreeNode));
root->val = rootvalue;//postorder[postorder_end -1];//这个是头结点
root->left = NULL;
root->right = NULL;//先初始化!!
if(preorder_end - preorder_start == 1)
{
return root;//只有一个节点的情况
}
int inorder_left_s = 0, inorder_left_e = 0;
int inorder_right_s =0, inorder_right_e = 0;
int preorder_left_s = 0, preorder_left_e = 0;
int preorder_right_s = 0, preorder_right_e = 0;
int middle_pos = 0;
/**分割中序数组:左右数组**/
for(middle_pos = inorder_start; middle_pos < inorder_end; middle_pos++)
{
if(inorder[middle_pos] == rootvalue)
{
break;
}
}
/**分开中序:左闭右开**/
inorder_left_s = inorder_start;
inorder_left_e = middle_pos;//
inorder_right_s = middle_pos + 1;
inorder_right_e = inorder_end;
/**分割前序序数组:左闭右开**/
preorder_left_s = preorder_start + 1;//第一个元素是头节点 排除
//preorder_start + 1是起始位置 , middle_pos - inorder_start是Size
preorder_left_e = preorder_start + 1 + middle_pos - inorder_start;
preorder_right_s = preorder_start + 1 + middle_pos - inorder_start;
preorder_right_e = preorder_end;
root->left = build(preorder, preorderSize, preorder_left_s, preorder_left_e, inorder, inorderSize, inorder_left_s, inorder_left_e);
root->right = build(preorder, preorderSize, preorder_right_s, preorder_right_e, inorder, inorderSize, inorder_right_s, inorder_right_e);
return root;
}
struct TreeNode* buildTree(int* preorder, int preorderSize, int* inorder, int inorderSize) {
if(preorderSize == 0 || inorderSize == 0)
{
return NULL;
}
return build(preorder, preorderSize, 0, preorderSize, inorder, inorderSize, 0 , inorderSize);
}