二叉树的所有路径(力扣257)

本文介绍了一种使用C++实现的方法,通过中序遍历二叉树并利用回溯技巧,找到所有从根节点到叶子节点的路径。Solution类中的binaryTreePaths函数是关键,它维护一个路径数组并递归地探索左、右子树。

解题思路:因为求的是路径,从根节点开始,所以采用中序遍历。并且要记录下路径,我们还要额外采用一个临时存放一条路径的容器,当遍历完一条时放入result中,再遍历另一条,这里采用的就是回溯了

具体代码如下:

class Solution {

private:

    void traversal(TreeNode* cur, vector<int>& path, vector<string>& result) {

        path.push_back(cur->val); // 中,中为什么写在这里,因为最后一个节点也要加入到path中

        // 这才到了叶子节点

        if (cur->left == NULL && cur->right == NULL) {

            string sPath;

            for (int i = 0; i < path.size() - 1; i++) {

                sPath += to_string(path[i]);

                sPath += "->";

            }

            sPath += to_string(path[path.size() - 1]);

            result.push_back(sPath);

            return;

        }

        if (cur->left) { // 左

            traversal(cur->left, path, result);

            path.pop_back(); // 回溯

        }

        if (cur->right) { // 右

            traversal(cur->right, path, result);

            path.pop_back(); // 回溯

        }

    }

public:

    vector<string> binaryTreePaths(TreeNode* root) {

        vector<string> result;

        vector<int> path;

        if (root == NULL) return result;

        traversal(root, path, result);

        return result;

    }

};

题目如下:

给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。

叶子节点 是指没有子节点的节点。

 

示例 1:

输入:root = [1,2,3,null,5]
输出:["1->2->5","1->3"]

示例 2:

输入:root = [1]
输出:["1"]
<think>好的,我现在需要解决用户的问题,即查找LeetCode257题的C语言实现代码或解决方案。首先,我得先明确LeetCode 257题的具体内容。根据记忆,LeetCode 257题是“二叉树的所有路径”,题目要求给定一个二叉树,返回所有从根节点到叶子节点的路径。 接下来,我需要回忆或查找该题的具体要求和示例。例如,输入可能是这样的二叉树: 1 / \ 2 3 \ 5 对应的输出应该是["1->2->5", "1->3"]。题目通常要求以字符串数组的形式返回所有路径,每个路径用箭头连接节点值。 现在,用户需要C语言的实现。由于C语言没有内置的字符串处理或动态数组结构,实现起来需要手动管理内存和字符串拼接,这会比用其他高级语言复杂一些。我需要考虑如何遍历二叉树,记录路径,并在到达叶子节点时将路径保存下来。 首先,二叉树的结构定义通常是这样的: struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; }; 接下来,遍历二叉树通常使用深度优先搜索(DFS),递归是比较直接的方法。在递归过程中,需要维护当前路径的字符串,并在叶子节点时将该路径添加到结果数组中。 但C语言中字符串操作较为繁琐,需要动态分配内存。例如,每次递归调用时,可能需要创建一个新的字符串来保存当前路径,或者使用一个缓冲区,并在适当的时候复制内容。同时,结果数组需要动态扩展,因为题目中路径的数量事先未知。 考虑到这些挑战,可能的实现步骤包括: 1. 编写递归函数遍历每个节点,传递当前路径字符串。 2. 当遇到叶子节点时,将当前路径添加到结果数组中。 3. 处理字符串拼接,包括添加箭头符号。 4. 管理内存,避免内存泄漏。 另外,需要注意递归的终止条件,即当节点为NULL时返回,当节点是叶子节点时处理路径。 在代码结构上,可能需要以下函数: - 主函数binaryTreePaths,初始化结果数组并调用递归函数。 - 递归辅助函数dfs,处理路径的构建和添加。 - 工具函数,如字符串拼接、结果数组的动态扩展。 例如,递归函数可能如下: void dfs(struct TreeNode* root, char* path, char*** result, int* returnSize, int* path_len) { if (!root) return; // 计算当前节点值的字符串长度 int len = snprintf(NULL, 0, "%d", root->val); char* num_str = malloc(len + 1); sprintf(num_str, "%d", root->val); // 如果是第一个节点,不需要添加箭头 if (*path_len == 0) { strcat(path, num_str); *path_len += len; } else { strcat(path, "->"); strcat(path, num_str); *path_len += len + 2; } if (!root->left && !root->right) { // 添加到结果数组 *result = realloc(*result, (*returnSize + 1) * sizeof(char*)); (*result)[*returnSize] = malloc(*path_len + 1); strcpy((*result)[*returnSize], path); (*returnSize)++; } else { dfs(root->left, path, result, returnSize, path_len); dfs(root->right, path, result, returnSize, path_len); } // 回溯,移除当前节点的部分 if (*path_len > len) { path[*path_len - len - 2] = '\0'; *path_len -= len + 2; } else { path[0] = '\0'; *path_len = 0; } free(num_str); } 不过,这样的实现可能存在问题,比如多次使用strcat可能导致缓冲区溢出,或者内存分配不够灵活。因此,可能需要更仔细地处理字符串的长度,提前分配足够的空间,或者在每次递归时创建新的字符串副本,避免修改原字符串带来的问题。 另一种方法是使用深度优先搜索,每次递归时传递当前路径的字符串,并在到达叶子节点时复制该字符串到结果数组中。这种方法可能需要更多的内存分配,但逻辑上更清晰。 例如: void dfs(struct TreeNode* root, char* current_path, char*** result, int* returnSize) { if (!root) return; char* val_str; int len = snprintf(NULL, 0, "%d", root->val); val_str = malloc(len + 1); sprintf(val_str, "%d", root->val); char* new_path; if (current_path[0] == '\0') { new_path = malloc(len + 1); strcpy(new_path, val_str); } else { int path_len = strlen(current_path); new_path = malloc(path_len + len + 3); // "->" + val_str + '\0' sprintf(new_path, "%s->%s", current_path, val_str); } if (!root->left && !root->right) { *result = realloc(*result, (*returnSize + 1) * sizeof(char*)); (*result)[*returnSize] = new_path; (*returnSize)++; } else { dfs(root->left, new_path, result, returnSize); dfs(root->right, new_path, result, returnSize); free(new_path); // 释放非叶子节点的路径 } free(val_str); } char** binaryTreePaths(struct TreeNode* root, int* returnSize) { char** result = NULL; *returnSize = 0; if (!root) return result; dfs(root, "", &result, returnSize); return result; } 不过,上述代码可能需要调整,比如初始调用时传递空字符串,并在每次递归时构建新的路径字符串,然后在叶子节点时保存,否则释放内存。这样可能更安全,但需要注意内存的正确释放,避免泄漏。 此外,C语言中的字符串处理需要格外小心,尤其是内存分配和释放。比如,每次构建new_path时需要足够大的空间,并且确保在非叶子节点递归后释放该路径,而只在叶子节点时保留路径字符串添加到结果数组中。 最后,返回的result数组中的每个字符串都需要在外部使用后由调用者释放,这也是C语言实现中常见的做法。 现在,我需要验证这个思路是否正确,并检查是否有潜在的错误。例如,初始调用时传递空字符串是否正确处理,递归过程中是否覆盖了正确的内容,以及内存是否被正确释放。 可能的问题包括: 1. 在构建new_path时,如果current_path为空,是否正确处理。 2. 内存分配是否足够,特别是计算路径长度时是否考虑了所有字符。 3. 是否在非叶子节点正确释放了new_path,避免内存泄漏。 例如,当current_path为空时,第一个节点的处理是否正确。比如,初始调用可能传递空字符串,导致第一次构建new_path时正确拼接节点的值。 另外,在叶子节点的情况下,new_path被添加到结果数组中,不需要释放,而非叶子节点在递归后必须释放new_path,否则会导致内存泄漏。 总结来说,正确的实现需要: - 递归遍历每个节点,构建路径字符串。 - 在叶子节点时保存路径字符串到结果数组。 - 在非叶子节点递归后释放临时路径字符串。 - 正确管理所有内存分配和释放。 根据上述思路,可以编写C语言代码。同时,参考用户提供的引用中的代码结构,例如使用动态数组和递归方法,如引用[1]中的栈实现,可能对处理路径有帮助。但需要注意,本题是二叉树问题,不同于栈的应用,但递归的处理方式类似。</think>### LeetCode 257题C语言实现:二叉树的所有路径 以下是使用深度优先搜索(DFS)递归实现的C语言解决方案: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; }; void dfs(struct TreeNode* root, char* path, char*** result, int* returnSize, int* path_len) { if (!root) return; // 转换当前节点值为字符串 char num_str[12]; int len = sprintf(num_str, "%d", root->val); // 路径拼接处理 if (*path_len > 0) { len += 2; // 添加"->" strcat(path, "->"); } strcat(path, num_str); *path_len += len; // 叶子节点处理 if (!root->left && !root->right) { *result = realloc(*result, (*returnSize + 1) * sizeof(char*)); (*result)[*returnSize] = malloc(*path_len + 1); strcpy((*result)[*returnSize], path); (*returnSize) += 1; } // 递归子节点 dfs(root->left, path, result, returnSize, path_len); dfs(root->right, path, result, returnSize, path_len); // 回溯:移除当前节点部分 path[*path_len - len] = '\0'; *path_len -= len; } char** binaryTreePaths(struct TreeNode* root, int* returnSize) { char** result = NULL; *returnSize = 0; if (!root) return result; char path[1024] = {0}; // 假设路径长度不超过1023字符 int path_len = 0; dfs(root, path, &result, returnSize, &path_len); return result; } ``` ### 实现说明 1. **数据结构**:使用`struct TreeNode`定义二叉树节点。 2. **路径拼接**:通过`sprintf`将整型值转换为字符串,动态计算存储空间。 3. **递归回溯**:每次递归后移除当前节点的路径部分,实现路径状态回溯。 4. **内存管理**:使用`realloc`动态扩展结果数组,每个路径字符串单独分配内存。 [^1]: 参考LeetCode官方对字符串拼接和树遍历的实现规范
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值