我的微信公众号获得了科技榜的第9名,平均阅读量第1的好成绩!

文章讲述了作者在公众号上坚持每天发布算法题,即使广告减少仍保持高质量内容,其关于LeetCode第113题路径总和II的解析展示了回溯算法的应用。作者凭借此策略获得了官方推荐,并分享了Java、C++和Python的代码实现。
摘要由CSDN通过智能技术生成

最近这两年公众号的日子确实不太好过,原因就是广告少了,大家挣不到钱了,所以渐渐发文的次数就少了,有的经常发一些没有营养的水文,还有一些停更了。

我早期写公众号完全是为了记录知识,就像大家写博客一样。虽然现在广告少了但我依然坚持知识的输出,每篇文章无论写什么,在最后必须要有一道算法题,这种坚持也得到了官方的认可,所以我的文章也经常会获得官方推荐。

今天我无意间看了一下最近的文章数据,发现竟然获得了新榜科技类的第9名,而我只是发了一篇文章,前8名都是发了3-12篇文章才超过我的,如果按照平均阅读量计算的话我已经甩开第二名好多。说明官方对咱还是很认可的,进一步说明了大家的眼光还是很不错的,关注了这么一个高质量的公众号855b5dbfcfa8419ecbcd572e1e059592.png

a99e9195dd1937e5741b76ebeb34a00d.png

文章被推荐的好处就是能够让大家认识到我,获得大家的关注,当然我也一定不负众望,继续坚持知识的输出,每天一道算法题,也欢迎大家一起来学习,同时也非常欢迎各位公众号博主和我交流。

f4859e63e123c4a3bc3950b57172dc80.png

--------------下面是今天的算法题--------------

来看一下今天的算法题,这题是LeetCode的第113题:路径总和 II,难度是中等,在阿里的面试中考过这道题,我们来看下。

564eaade02d4b3405304d1a2b2c5a216.png

问题描述

来源:LeetCode第113题

难度:中等

给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有从根节点到叶子节点路径总和等于给定目标和的路径。

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

示例1:

491ee21ad9f0dd238f2f6822a1550f2a.jpeg

输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22

输出:[[5,4,11,2],[5,8,4,5]]

示例2:

0465a261cfea925809b5a94014aca3aa.jpeg

输入:root = [1,2,3], targetSum = 5

输出:[]

  • 树中节点总数在范围 [0, 5000] 内

  • -1000 <= Node.val <= 1000

  • -1000 <= targetSum <= 1000

问题分析

这题让找出所有从根节点到叶子节点路径总和等于给定目标和的路径,前几天我们刚讲过路径总和,不过前面这道题判断是否存在这样的一个路径,而这题是让找出所有符合的路径。

这题可以使用回溯算法解决,有两种不同的写法,一种是累加一种是累减。累加就是从根节点一直累加下去,到叶子节点的时候如果累加的值等于targetSum,说明从根节点到当前叶子节点这条路径是符合条件的,要保存下来。

累减就是从根节点开始用targetSum减去当前节点的值,到叶子节点的时候如果减完之后targetSum为0,说明从根节点到当前叶子节点这条路径也是符号条件的。这两种写法我们随便选择一个即可。

如下图所示,使用的是累减的方式,其中从根节点到橙色路径都是符合条件的。关于回溯算法以及使用模板,如果大家不熟悉的可以看下我的书中《算法秘籍》的第6章。

074c443ea5faaeb7ce98ea3673eea3ea.png

JAVA:

public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
    List<List<Integer>> ans = new ArrayList<>();// 存放结果的集合
    List<Integer> path = new ArrayList<>();// 存放从根节点到叶子节点的值
    dfs(root, targetSum, path, ans);// dfs遍历
    return ans;
}

public void dfs(TreeNode cur, int targetSum, List<Integer> path,
                List<List<Integer>> ans) {
    if (cur == null)// 节点为空,直接返回
        return;
    path.add(cur.val);// 把当前节点的值添加到路径path中
    // 如果是叶子节点,当前节点的值等于targetSum,就把当前路径添加进来
    if (cur.left == null && cur.right == null && targetSum == cur.val) {
        ans.add(new ArrayList<>(path));
    } else {
        // 沿着当前树的左右子节点往下遍历,这里要注意targetSum的值要减去当前节点的值
        dfs(cur.left, targetSum - cur.val, path, ans);
        dfs(cur.right, targetSum - cur.val, path, ans);
    }
    path.remove(path.size() - 1);// 回溯,把最后一个添加的节点给移除
}

C++:

public:
    vector<vector<int>> pathSum(TreeNode *root, int targetSum) {
        vector<vector<int>> ans;// 存放结果的集合
        vector<int> path;// 存放从根节点到叶子节点的值
        dfs(root, targetSum, path, ans);// dfs遍历
        return ans;
    }

    void dfs(TreeNode *cur, int targetSum, vector<int> &path,
             vector<vector<int>> &ans) {
        if (!cur)// 节点为空,直接返回
            return;
        path.push_back(cur->val);// 把当前节点的值添加到路径path中
        // 如果是叶子节点,当前节点的值等于targetSum,就把当前路径添加进来
        if (cur->left == nullptr && cur->right == nullptr && targetSum == cur->val) {
            ans.push_back(path);
        } else {
            // 沿着当前树的左右子节点往下遍历,这里要注意targetSum的值要减去当前节点的值
            dfs(cur->left, targetSum - cur->val, path, ans);
            dfs(cur->right, targetSum - cur->val, path, ans);
        }
        path.pop_back();// 回溯,把最后一个添加的节点给移除
    }

C:

void dfs(struct TreeNode *cur, int targetSum, int *path, int **ans, int *retSize, int *retColSize, int pathSize) {
    if (!cur)// 节点为空,直接返回
        return;
    path[pathSize++] = cur->val;// 把当前节点的值添加到路径path中
    // 如果是叶子节点,当前节点的值等于targetSum,就把当前路径添加进来
    if (cur->left == NULL && cur->right == NULL && targetSum == cur->val) {
        int *tmp = malloc(sizeof(int) * pathSize);
        memcpy(tmp, path, sizeof(int) * pathSize);
        ans[*retSize] = tmp;
        retColSize[(*retSize)++] = pathSize;
    } else {
        // 沿着当前树的左右子节点往下遍历,这里要注意targetSum的值要减去当前节点的值
        dfs(cur->left, targetSum - cur->val, path, ans, retSize, retColSize, pathSize);
        dfs(cur->right, targetSum - cur->val, path, ans, retSize, retColSize, pathSize);
    }
    pathSize--;// 回溯,把最后一个添加的节点给移除
}

int **pathSum(struct TreeNode *root, int targetSum, int *returnSize, int **returnColumnSizes) {
    int **ans = malloc(sizeof(int *) * 2001);// 存放结果的集合
    int *path = malloc(sizeof(int) * 2001);// 存放从根节点到叶子节点的值
    int retSize = 0;
    int *retColSize = malloc(sizeof(int) * 2001);
    dfs(root, targetSum, path, ans, &retSize, retColSize, 0);// dfs遍历
    *returnColumnSizes = retColSize;
    *returnSize = retSize;
    return ans;
}

Python:

def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
    ans = list()  # 存放结果的集合
    path = list()  # 存放从根节点到叶子节点的值

    def dfs(cur: TreeNode, targetSum: int):
        if not cur:  # 节点为空,直接返回
            return
        path.append(cur.val)  # 把当前节点的值添加到路径path中
        # 如果是叶子节点,当前节点的值等于targetSum,就把当前路径添加进来
        if not cur.left and not cur.right and targetSum == cur.val:
            ans.append(path[:])
        else:
            # 沿着当前树的左右子节点往下遍历,这里要注意targetSum的值要减去当前节点的值
            dfs(cur.left, targetSum - cur.val)
            dfs(cur.right, targetSum - cur.val)
        path.pop()  # 回溯,把最后一个添加的节点给移除

    dfs(root, targetSum)  # dfs遍历
    return ans

3240698b4b63d112fee3fb9e950442ad.gif

笔者简介

博哥,真名:王一博,毕业十多年,《算法秘籍》作者,专注于数据结构和算法的讲解,在全球30多个算法网站中累计做题2000多道,在公众号中写算法题解700多题,对算法题有自己独特的解题思路和解题技巧,喜欢的可以给个关注,也可以下载我整理的1000多页的PDF算法文档。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

数据结构和算法

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

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

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

打赏作者

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

抵扣说明:

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

余额充值