自学内容网 自学内容网

代码随想录算法训练营第十四天|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)!