二叉树的所有路径


文章内容是自己刷leetcode题目的一些总结。
文章内容参考公众号: 代码随想录
喜欢的话,希望大家可以点点赞 ^ - ^

一.题目描述

在这里插入图片描述

二.题目分析

我们需要找到所有路径,要用到递归+回溯。

使用path保存每条路径,遇到叶子节点就把path加入到答案ans中去。

使用前序遍历,每次先将节点加入到path,终止条件为遇到叶子节点,也就是该节点的左右孩子都为空的节点,注意,要先将节点加入path,再进行终止条件的判断,否则叶子节点会加不进去。单次递归逻辑为:递归左右子树,递归完成后记得回溯。

三.递归代码

class Solution {
public:
    void getPath(TreeNode* node, vector<int>& path, vector<string>& ans) {
        path.push_back(node->val); //中
        //终止条件:遇到叶子节点
        if(node->left == nullptr && node->right == nullptr) {
            string sPath;
            for(int i = 0; i < path.size() - 1; i ++) {
                sPath += to_string(path[i]);
                sPath += "->";
            }
            sPath += to_string(path[path.size() - 1]);
            ans.push_back(sPath);
        }

        //单次逻辑:递归+回溯
        if(node->left) {  //左
            getPath(node->left, path, ans);
            path.pop_back();
        }
        if(node->right) {  //右
            getPath(node->right, path, ans);
            path.pop_back();
        }

    }
    vector<string> binaryTreePaths(TreeNode* root) {
        //使用递归+回溯
        //因为要记录路径,所以采用前序遍历
        vector<int> path;
        vector<string> ans;
        if(root == nullptr) return ans;
        getPath(root, path, ans);
        return ans;
    }
};

四.拓展:路径总和

1.题目描述

在这里插入图片描述

2.题目分析

这道题目其实与我们刚刚讲的二叉树的所有路径很相似。我们可以在找到一条路径path后将该路径的节点的值求和来判断是不是我们需要的那条路径。找到后做一个标记返回。

改进:其实我们不用统计每条路径之后再按照路径求和,我们可以在和的基础上进行减法,当遇到叶子节点时,减到了0说明找到路径,否则就是没找到。

因为我们的目标是找到一条路径即可,所以不用遍历整个树,返回值采用bool。

3.递归代码

原始:
class Solution {
public:
    int flag = 0;
    bool hasSum(TreeNode* node, int n, vector<int>& path) {
        // if(node == nullptr) return false;
        path.push_back(node->val);
        
        if(node->left == nullptr && node->right == nullptr) {
            int sum = 0;
            for(int i = 0; i < path.size() - 1; i ++) {
                sum += path[i];
            }
            sum += path[path.size() - 1];
            if(sum == n) {
                flag = 1;
                return true;
            }
            else return false;
        }
        

        if(node->left) {
            hasSum(node->left, n, path);
            path.pop_back();
        }
        if(node->right) {
            hasSum(node->right, n, path);
            path.pop_back();
        }
        if(flag == 1) {
            return true;
        } else {
            return false;
        }
    }
    bool hasPathSum(TreeNode* root, int targetSum) {
        if(root == nullptr) return false;
        vector<int> path;
        return hasSum(root, targetSum, path);
    }
};
改进:
class Solution {
public:
    bool hasSum(TreeNode* node, int cnt) {
        //因为我们不用遍历整棵树,找到一条合适的边就可以返回,所以用bool

        //终止条件
        if(!node->left && !node->right && cnt == 0) return true; //找到了
        if(!node->left && !node->right) return false; //没找到

        //递归逻辑
        if(node->left) {
            cnt -= node->left->val;
            if(hasSum(node->left, cnt)) return true;
            cnt += node->left->val; //回溯
        }

        if(node->right) {
            cnt -= node->right->val;
            if(hasSum(node->right, cnt)) return true;
            cnt += node->right->val; //回溯
        }

        return false;
    }
    
    bool hasPathSum(TreeNode* root, int targetSum) {
        if(root == nullptr) return false;
       
        return hasSum(root, targetSum - root->val);
    }
};

五.总结

在这次题解中,我们用到了回溯,其实递归与回溯是相伴相生的,我会在二叉树的章节更新完成后,开始给大家讲解回溯的相关题目。

可以使用递归的方式来实现求解二叉树所有路径的功能。具体实现方法如下: 1. 定义一个函数,输入参数为当前节点指针、当前路径字符串和结果数组。 2. 如果当前节点为空,则直接返回。 3. 将当前节点的值添加到当前路径字符串中。 4. 如果当前节点为叶子节点,则将当前路径字符串添加到结果数组中。 5. 否则,递归遍历当前节点的左子树和右子树,分别调用上述函数。 6. 递归结束后,将当前节点的值从当前路径字符串中删除,以便遍历其它路径。 下面是具体的 C 代码实现: ``` #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_PATH_LEN 100 struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; }; void binaryTreePathsHelper(struct TreeNode* node, char* path, char** result, int* returnSize) { if (node == NULL) { return; } int len = strlen(path); if (len > ) { path[len] = '-'; path[len+1] = '>'; path[len+2] = '\'; } char val_str[10]; sprintf(val_str, "%d", node->val); strcat(path, val_str); if (node->left == NULL && node->right == NULL) { result[*returnSize] = (char*)malloc(sizeof(char) * (strlen(path) + 1)); strcpy(result[*returnSize], path); (*returnSize)++; } else { binaryTreePathsHelper(node->left, path, result, returnSize); binaryTreePathsHelper(node->right, path, result, returnSize); } path[strlen(path) - strlen(val_str) - 2] = '\'; } char ** binaryTreePaths(struct TreeNode* root, int* returnSize) { char** result = (char**)malloc(sizeof(char*) * MAX_PATH_LEN); *returnSize = ; char path[MAX_PATH_LEN]; path[] = '\'; binaryTreePathsHelper(root, path, result, returnSize); return result; } int main() { struct TreeNode* root = (struct TreeNode*)malloc(sizeof(struct TreeNode)); root->val = 1; root->left = (struct TreeNode*)malloc(sizeof(struct TreeNode)); root->left->val = 2; root->left->left = NULL; root->left->right = (struct TreeNode*)malloc(sizeof(struct TreeNode)); root->left->right->val = 5; root->left->right->left = NULL; root->left->right->right = NULL; root->right = (struct TreeNode*)malloc(sizeof(struct TreeNode)); root->right->val = 3; root->right->left = NULL; root->right->right = NULL; int returnSize; char** result = binaryTreePaths(root, &returnSize); for (int i = ; i < returnSize; i++) { printf("%s\n", result[i]); } return ; } ``` 运行结果如下: ``` 1->2->5 1->3 ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Echo夏末

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值