Path Sum三个题目

一个二叉树,是否存在从根节点到叶子节点的路径,其节点的值的和为指定整数,如果有,打印出所有数组。

需如下树节点求和

    5
     /  
   4     8
    /     /  
  11  13    4
  /       /  
  7    2      5   1

JavaScript实现

window.onload = function() {
    var n1 = new TreeNode(1, null, null),
        n51 = new TreeNode(5, null, null),
        n2 = new TreeNode(2, null, null),
        n7 = new TreeNode(7, null, null),
        n42 = new TreeNode(4, n51, n1),
        n13 = new TreeNode(13, null, null),
        n11 = new TreeNode(11, n7, n2),
        n8 = new TreeNode(8, n13, n42),
        n4 = new TreeNode(4, n11, null),
        n5 = new TreeNode(5, n4, n8);

    var sum = 22;

    var res = getPathSum(n5, sum);
    console.log('res: ', res);

    var has = hasPathSum(n5,22);
    console.log('has: ', has);

    var count = pathCount(n5,22);
    console.log('count: ', count);
}

function TreeNode(val, left, right) {
    this.val = val;
    this.left = left;
    this.right = right;
}

//path sum i(https://leetcode-cn.com/problems/path-sum-i/)
function hasPathSum(root, sum) {
    if (root == null) return false;

    sum -= root.val;

    if (sum == 0 && root.left == null && root.right == null) return true;

    return hasPathSum(root.left, sum) || hasPathSum(root.right, sum);
}

//path sum ii(https://leetcode-cn.com/problems/path-sum-ii/)
function getPathSum(root, sum) {
    var res = [],path = [];
    dfs(root, sum, path, res);
    return res;
}

function dfs(root,sum,path,res){
    if(root == null) return;

    sum -= root.val;
    path.push(root.val);

    if(sum == 0 && root.left == null && root.right == null){
        res.push(copy(path));
        //这句可以加,也可以不加, 加上,可以减少后面的两个dfs内部的null判断,因为此时root的left和right都为null
        return path.pop();
    }

    dfs(root.left,sum,path,res);
    dfs(root.right,sum,path,res);

    path.pop();
}

function copy(a){
    return JSON.parse(JSON.stringify(a))
}

//path sum iii(https://leetcode-cn.com/problems/path-sum-iii/)
function pathCount(root,sum){
    return helper(root,sum,[],0);
}

//思路就是,深度优先遍历所有节点,用path记录从根节点到该节点的路径
//由于只计算从上到下的节点和,所以从当前节点沿着path向上求和
//到合适的节点就计数,直至到根节点,当前节点为终点的所有路径计数完毕
function helper(root,sum,path,p){
    if(root == null) return 0;
    //记录当前节点的值
    path[p] = root.val;
    //path此时记录的是根节点到当前节点的路径上的所有节点
    let temp = 0, n=0;
    //p是当前节点的位置,从当前节点开始向根节点一路做加法
    for(let i=p;i>=0;i--){
        temp += path[i];
        //当前节点加到某节点符合,就计数,由于节点值可能为0或负值,此处不能break,还需继续计算
        if(temp == sum) n++;
    }
    //path虽然是引用传递,但是left和right用的是同一个索引p+1,所以path中的值会被覆盖
    //path中的值始终是到当前节点的路径值,不需要拷贝数组,也不需要弹出已经访问的值
    let left = helper(root.left,sum,path,p+1);
    let right = helper(root.right,sum,path,p+1);

    return n + left + right;
}
原文地址:https://www.cnblogs.com/mengff/p/6186736.html