LeetCode--路径总和(二叉树 路径总和 回溯法)

                                                路径总和

路径总和1

给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。

说明: 叶子节点是指没有子节点的节点。

示例: 

给定如下二叉树,以及目标和 sum = 22,

              5

             / \

            4   8

           /   / \

          11  13  4

         /  \      \

        7    2      1

返回 true, 因为存在目标和为 22 的根节点到叶子节点的路径 5->4->11->2。

思路1 双栈 

/**
 * @Author liuhaidong
 * @Description 运用栈的方式
 * @param
 * @Date 12:08 2019/10/8 0008
 */
public static boolean hasPathSum1(TreeNode root, int sum) {
    if (root == null) {
        return false;
    }
    Stack<TreeNode> path = new Stack<>();
    //存放节点
    Stack<Integer> sub = new Stack<>();
    //存放节点的值
    path.push(root);
    sub.push(root.val);
    while(!path.isEmpty()){
        TreeNode temp = path.pop();
        int tempVal = sub.pop();

        if(temp.left == null && temp.right == null) {
            if (tempVal == sum) {
                return true;
            }
        }else {
                if(temp.left != null){
                    path.push(temp.left);
                    sub.push(temp.left.val + tempVal);
                }
                if(temp.right != null){
                    path.push(temp.right);
                    sub.push(temp.right.val + tempVal);
                }
            }
        }

    return false;
}

递归

最直接的方法就是利用递归,遍历整棵树:如果当前节点不是叶子,对它的所有孩子节点,递归调用 hasPathSum 函数,其中 sum 值减去当前节点的权值;如果当前节点是叶子,检查 sum 值是否为 0,也就是是否找到了给定的目标和。

(从根节点开始,每当遇到一个节点的时候,从目标值里扣除节点值,一直到叶子节点判断目标值是不是被扣完)

class Solution {
  public boolean hasPathSum(TreeNode root, int sum) {
    if (root == null){
     //这个地方是防止出现return hasPathSum(root.left, sum) || hasPathSum(root.right, sum);
      //里面root.left,root.right为空的情况
      return false;
    }

    sum -= root.val;
    if ((root.left == null) && (root.right == null))
      return (sum == 0);
    return hasPathSum(root.left, sum) || hasPathSum(root.right, sum);
  }
}

主函数

public static void main(String[] args) {
    TreeNode root = new TreeNode(5);
    TreeNode node1 = new TreeNode(4);
    TreeNode node2 = new TreeNode(8);
    TreeNode node3 = new TreeNode(11);
    TreeNode node4 = new TreeNode(7);
    TreeNode node5 = new TreeNode(2);
    TreeNode node6 = new TreeNode(13);
    TreeNode node7 = new TreeNode(4);
    TreeNode node8 = new TreeNode(1);
    root.left=node1;
    root.right=node2;
    node1.left=node3;
    node3.left=node4;
    node3.right=node5;
    node2.left=node6;
    node2.right=node7;
    node7.right=node8;
    System.out.println(hasPathSum1(root,22));
}
public class TreeNode {
          int val;
     TreeNode left;
     TreeNode right;
      TreeNode(int x) { val = x; }

}

路径总和2

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

说明: 叶子节点是指没有子节点的节点。

示例:
给定如下二叉树,以及目标和 sum = 22,

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

返回:

[
   [5,4,11,2],
   [5,8,4,5]
]
public static void main(String[] args) {
        TreeNode root1 = new TreeNode(10);
        TreeNode node1 = new TreeNode(5);
        TreeNode node2 = new TreeNode(12);
        TreeNode node3 = new TreeNode(4);
        TreeNode node4 = new TreeNode(7);
//        TreeNode node5 = new TreeNode(6);
//        TreeNode node6 = new TreeNode(7);
        root1.left=node1;
        root1.right=node2;
        node1.left =node3;
        node1.right = node4;
//        node2.left = node5;
//        node2.right = node6;
        System.out.println(pathSum(root1,22));
    }
    public static List<List<Integer>> paths = new ArrayList<>();
    public static List<List<Integer>> pathSum(TreeNode root, int sum) {
        go(root,0,sum,new ArrayList<>());
        return paths;
    }
 
    public static void go(TreeNode node,int sum,int target,ArrayList<Integer> path){
        if(node==null){
            return;
        }
        sum+=node.val;
        path.add(node.val);
        //判断该路径和是否符合目标值
        if(sum==target&&node.left==null&&node.right==null){
            //因为要子节点,所以它的左子树和右子树必须为null
            paths.add(new ArrayList<>(path));
        }else{
            go(node.left,sum,target,path);
            go(node.right,sum,target,path);
        }
        //回溯
        path.remove(path.size()-1);
    }

全部评论

相关推荐

感觉这一周太梦幻了,就像一个梦,很不真实~~~感觉这个暑期,我的运气占了99成,实力只有百分之一4.15上午&nbsp;腾讯csig&nbsp;腾讯云部门,面完秒进入复试状态4.16下午&nbsp;美团优选供应链部门,4.18上午发二面4.17晚上&nbsp;阿里国际一面,纯拷打,面完我都玉玉了4.18下午&nbsp;阿里国际二面,是我们leader面的我,很轻松~~4.18晚上&nbsp;约了hr面4.19上午&nbsp;hr面,下午两点口头oc4.19晚上&nbsp;意向书说起来我的暑期好像一次都没挂过~~~~~难道我是天生面试圣体?----------------------------------------------------------------------六个月前,我还是0项目0刷题,当时想的是先把论文发出来再去找实习。结果一次组会,老师打破了我的幻想(不让投B会,只让投刊或者A)我拿头投啊!!!然后就开始物色着找实习,顺便做完了mit的6.s081,但是基本上还是没刷过题目-----------------------------------------------------------------------11月&nbsp;&nbsp;一次偶然的机会,面进了某个耳机厂的手环部门,大概是做嵌入式的,用的是CPP。12月&nbsp;莫名其妙拿到了国创的面试机会,0基础四天速成java基础!居然也给我面过了hhhhh,可能是面试没写题吧入职国创后的几个月,一直没活,天天搁那看剧,都快忘了还有暑期实习这回事了~~~~命运的齿轮在2.26开始转动,因为这一天美团开了,我开始慌了,因为那时的我什么都不会。lc,八股,sql全部是0进度。然后就开始了女娲补天,上班刷题,下班继续做之前的开源,顺便学一学八股。3月到现在,lc也刷到快200了,一天最多提交了47次~~~~~~~~~~八股根据别人的面经总结和博客,写了快十万字的笔记~~~~~~~~~~简历上的实习经历和开源,也努力去深挖了,写了几万字的记录~~~~~~所以面试的时候,基本上都能cover了,面试官问到的基础基本都会,不基础的我就把他往我会的地方引。结果好像还不错,基本上每个面试官评价都挺好的emmmmmmmm
投递阿里巴巴等公司10个岗位
点赞 评论 收藏
转发
科大讯飞消费者bg二级研究院 语音算法岗 24k*14
点赞 评论 收藏
转发
点赞 收藏 评论
分享
牛客网
牛客企业服务