题目一
题目描述
思路
1.先解释一下函数第二个参数的意思,因为二叉树是逻辑结构,存储结构是数组,leetcode题目设计的就是不知道数组的大小,因此函数外部会传入一个变量,函数形参用returnSize指针来接收该变量地址,目的就是为了能够改变外部的数组大小的变量~
2. 数组空间是malloc出来的,但是我们并不知道要开多大空间,因此自己定义了求节点个数的函数
int TreeSize(struct TreeNode* root)
{
return root == NULL? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}
第一次提交时代码
int TreeSize(struct TreeNode* root)
{
return root == NULL? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}
void _preorder(struct TreeNode* root, int* a, int i)
{
if(root == NULL)
return;
a[i++] = root->val;
_preorder(root->left, a, i);
_preorder(root->right, a, i);
}
int* preorderTraversal(struct TreeNode* root, int* returnSize){
*returnSize = TreeSize(root);
int* a = (int*)malloc(*returnSize *sizeof(int));
int i = 0;
_preorder(root, a, i);
return a;
}
分析错误原因:
解决方案:传i的地址&i,用*pi来接收i的地址,这样的话每一个栈帧虽然都有一个pi,但是这些pi都指向了i,直接(*pi)++即可
正确代码
int TreeSize(struct TreeNode* root)
{
return root == NULL? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}
void _preorder(struct TreeNode* root, int* a, int* pi)
{
if(root == NULL)
return;
a[(*pi)++] = root->val;
_preorder(root->left, a, pi);
_preorder(root->right, a, pi);
}
int* preorderTraversal(struct TreeNode* root, int* returnSize){
*returnSize = TreeSize(root);
int* a = (int*)malloc(*returnSize *sizeof(int));
int i = 0;
_preorder(root, a, &i);
return a;
}
ps:想使用全局变量也是可以的,但是要注意leetcode的特点,他会多次调用你写的函数,所以下面这种写法就是有问题的~
可以看到出了内存错误,而且是第二个测试用例没过,就是因为第二次调用函数时i还是保留了上一次的值,导致a[i++] = root->val 下标越界~
所以记得把i初始化成0
正确代码
int i = 0;
int TreeSize(struct TreeNode* root)
{
return root == NULL? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}
void _preorder(struct TreeNode* root, int* a)
{
if(root == NULL)
return;
a[i++] = root->val;
_preorder(root->left, a);
_preorder(root->right, a);
}
int* preorderTraversal(struct TreeNode* root, int* returnSize){
*returnSize = TreeSize(root);
int* a = (int*)malloc(*returnSize *sizeof(int));
i = 0;
_preorder(root, a);
return a;
}
还是不推荐使用全局变量哦~
题目二
题目描述
这道题遍历比较特殊,因为题中给的是二叉树前序遍历的结果,要求实现中序遍历,因此我们需要先根据前序遍历结果构建出二叉树,然后进行中序遍历
根据前序构建二叉树
技巧:NULL是结束的标志,是构建根结束的标志,是构建左子树结束的标志,同样也是构建右子树结束的标志~
把握住前序的关键:每棵树的遍历顺序都要是根-左子树-右子树
代码实现
#include <stdio.h>
#include <stdlib.h>
typedef char BTDataType;
typedef struct BinaryTreeNode
{
BTDataType data;
struct BinaryTreeNode* left;
struct BinaryTreeNode* right;
}BTNode;
BTNode* BuyNode(BTDataType x)
{
BTNode* node = (BTNode*)malloc(sizeof(BTNode));
if(node == NULL)
{
perror("malloc fail\n");
return NULL;
}
node->data = x;
node->left = NULL;
node->right = NULL;
return node;
}
BTNode* CreateTree(char* a, int* pi)
{
if(a[*pi] == '#')
{
(*pi)++;
return NULL;
}
BTNode* root = BuyNode(a[*pi]);
(*pi)++;
root->left = CreateTree(a,pi);
root->right = CreateTree(a,pi);
return root;
}
void InOrder(BTNode* root)
{
if(root == NULL)
return;
InOrder(root->left);
printf("%c ",root->data);
InOrder(root->right);
}
int main() {
char a[100];
scanf("%s",a);
int i = 0;
BTNode* root = CreateTree(a, &i);
InOrder(root);
printf("\n");
}
代码中同样用到了pi指针,通过上一道题大家应该已经明白了为什么要传i地址了~
本篇文章就分享到这了,欢迎大家交流指正~