代码随想录算法训练营第十四天|Day14二叉树
110.平衡二叉树
题目链接/文章讲解/视频讲解:https://programmercarl.com/0110.%E5%B9%B3%E8%A1%A1%E4%BA%8C%E5%8F%89%E6%A0%91.html
思路
1.递归
1.明确递归函数的参数和返回值
参数:当前传入节点。 返回值:以当前传入节点为根节点的树的高度。
2.明确终止条件
递归的过程中依然是遇到空节点了为终止,返回0,表示当前节点为根节点的树高度为0
3.明确单层递归的逻辑
如何判断以当前传入节点为根节点的二叉树是否是平衡二叉树呢?
当然是其左子树高度和其右子树高度的差值。分别求出其左右子树的高度,然后如果差值小于等于1,则返回当前二叉树的高度,否则返回-1,表示已经不是二叉平衡树了。
int getDepth(struct TreeNode* node) {
if(!node)
return 0;
int rightDepth = getDepth(node->right);
int leftDepth = getDepth(node->left);
return rightDepth > leftDepth ? rightDepth + 1 : leftDepth + 1;
}
bool isBalanced(struct TreeNode* root) {
if(!root)
return 1;
int leftDepth = getDepth(root->left);
int rightDepth = getDepth(root->right);
int diff;
if((diff = leftDepth - rightDepth) > 1 || diff < -1)
return 0;
return isBalanced(root->right) && isBalanced(root->left);
}
2.迭代
可以先定义一个函数,专门用来求高度。这个函数通过栈模拟的后序遍历找每一个节点的高度(其实是通过求传入节点为根节点的最大深度来求的高度)
int getDepth(struct TreeNode* node) {
struct TreeNode** stack = (struct TreeNode**)malloc(sizeof(struct TreeNode*) * 10000);
int stackTop = 0;
if(node)
stack[stackTop++] = node;
int result = 0;
int depth = 0;
while(stackTop) {
struct TreeNode* tempNode = stack[--stackTop];
if(tempNode) {
depth++;
stack[stackTop++] = tempNode;
stack[stackTop++] = NULL;
if(tempNode->left)
stack[stackTop++] = tempNode->left;
if(tempNode->right)
stack[stackTop++] = tempNode->right;
result = result > depth ? result : depth;
}
else {
tempNode = stack[--stackTop];
depth--;
}
}
return result;
}
bool isBalanced(struct TreeNode* root){
struct TreeNode** stack = (struct TreeNode**)malloc(sizeof(struct TreeNode*) * 10000);
int stackTop = 0;
if(!root)
return 1;
stack[stackTop++] = root;
while(stackTop) {
struct TreeNode* node = stack[--stackTop];
int diff = getDepth(node->right) - getDepth(node->left);
if(diff > 1 || diff < -1)
return 0;
if(node->left)
stack[stackTop++] = node->left;
if(node->right)
stack[stackTop++] = node->right;
}
return 1;
}
学习反思
对二叉树有了更深刻的认知.
257. 二叉树的所有路径
思路
这道题目要求从根节点到叶子的路径,所以需要前序遍历,这样才方便让父节点指向孩子节点,找到对应的路径。
在这道题目中将第一次涉及到回溯,因为我们要把路径记录下来,需要回溯来回退一个路径再进入另一个路径。
// 动态数组结构体以存储路径
typedef struct {
char** paths; // 存储路径的指针数组
int size; // 当前路径数量
int capacity; // 当前路径数组的容量
} PathList;
// 创建路径列表
PathList* createPathList(int capacity) {
PathList* list = (PathList*)malloc(sizeof(PathList));
list->paths = (char**)malloc(capacity * sizeof(char*));
list->size = 0;
list->capacity = capacity;
return list;
}
// 追加路径到路径列表
void addPath(PathList* list, const char* path) {
if (list->size == list->capacity) {
list->capacity *= 2; // 扩展容量
list->paths = (char**)realloc(list->paths, list->capacity * sizeof(char*));
}
list->paths[list->size] = strdup(path); // 复制字符串
list->size++;
}
// 递归查找路径
void findPaths(struct TreeNode* root, char* path, PathList* list) {
if (root == NULL) return;
// 保存当前节点的值
char buffer[20]; // 存储当前节点的值的字符串
snprintf(buffer, sizeof(buffer), "%d", root->val);
// 如果当前路径为空,则直接添加当前节点的值
if (strlen(path) == 0) {
strcat(path, buffer);
} else {
strcat(path, "->");
strcat(path, buffer); // 正确拼接
}
// 检查是否是叶子节点
if (root->left == NULL && root->right == NULL) {
addPath(list, path); // 记录完整路径
} else {
// 递归遍历左子树和右子树
findPaths(root->left, path, list);
findPaths(root->right, path, list);
}
// 回溯,移除当前节点的值以便在其他路径中使用
// 注意:在这里不需要查找最后一个箭头而是直接去掉当前节点的字符串
size_t len = strlen(path);
if (len > 0) {
size_t pathLen = strlen(buffer);
if (len >= pathLen + 2) { // len - 2是为了考虑去掉箭头和当前节点
path[len - (pathLen + 2)] = '\0'; // 保留路径的前一部分
} else {
path[0] = '\0'; // 确保字符串为空
}
}
}
// 主函数,用于返回所有从根到叶子的路径
char** binaryTreePaths(struct TreeNode* root, int* returnSize) {
PathList* list = createPathList(10); // 初始化路径列表
char path[200] = ""; // 用于存储当前路径
findPaths(root, path, list); // 查找所有路径
*returnSize = list->size; // 返回路径数量
return list->paths; // 返回路径数组
}
// 释放路径列表和每个路径字符串的内存
void freePathList(PathList* list) {
for (int i = 0; i < list->size; i++) {
free(list->paths[i]); // 释放每个路径字符串
}
free(list->paths); // 释放路径数组
free(list); // 释放路径列表结构
}
// 释放树节点的内存
void freeTree(struct TreeNode* root) {
if (root) {
freeTree(root->left);
freeTree(root->right);
free(root);
}
}
// 创建新节点
struct TreeNode* createNode(int val) {
struct TreeNode* node = (struct TreeNode*)malloc(sizeof(struct TreeNode));
node->val = val;
node->left = NULL;
node->right = NULL;
return node;
}
学习反思
我自己写出来的有问题,改了好久,c语言好烦。
404.左叶子之和
int sumOfLeftLeaves(struct TreeNode* root){
if(!root)
return 0;
int leftValue = sumOfLeftLeaves(root->left);
int rightValue = sumOfLeftLeaves(root->right);
int midValue = 0;
if(root->left && (!root->left->left && !root->left->right))
midValue = root->left->val;
return leftValue + rightValue + midValue;
}
学习反思
相对来简单一点。
222.完全二叉树的节点个数
题目链接/文章讲解/视频讲解:https://programmercarl.com/0222.%E5%AE%8C%E5%85%A8%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E8%8A%82%E7%82%B9%E4%B8%AA%E6%95%B0.html
思路
1.递归
int countNodes(struct TreeNode* root) {
if(!root)
return 0;
int leftCount = countNodes(root->left);
int rightCount = countNodes(root->right);
return leftCount + rightCount + 1;
}
int countNodes(struct TreeNode* root){
return getNodes(root);
}
2.迭代
int countNodes(struct TreeNode* root){
int totalNum = 0;
struct TreeNode** stack = (struct TreeNode**)malloc(sizeof(struct TreeNode*) * 100);
int stackTop = 0;
if(root)
stack[stackTop++] = root;
while(stackTop) {
struct TreeNode* tempNode = stack[--stackTop];
totalNum++;
if(tempNode->left)
stack[stackTop++] = tempNode->left;
if(tempNode->right)
stack[stackTop++] = tempNode->right;
}
return totalNum;
}
学习反思
对二叉树有了更深刻的认知。
总结
破防的一天,第二个题改了好久,还是要认真反思。加油!!!
原文地址:https://blog.csdn.net/a6666999d/article/details/142925509
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!