DFS习题-LeetCode

1、Path Sum

题目:

Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum.

Note: A leaf is a node with no children.

Example:

Given the below binary tree and sum = 22,

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

return true, as there exist a root-to-leaf path 5->4->11->2 which sum is 22.

分析:leetcode上一个关于DFS最简单的题目了,根据题意很容易用DFS来做,不过因为不知道树的大小,所以不能用visited数组来标识是否访问过。关键在于如何判断和为sum,第一个思路是用一个stack来保存访问过的root.val,回溯的过程就删掉最近的一个;第二个思路是每次递归都将问题化简为小子树,求和变成sum-root.val。

1 public boolean hasPathSum(TreeNode root, int sum) {
2         if ( root == null ) return false;
3         TreeNode t = root;
4         if ( t.left == null && t.right == null && sum - t.val == 0)  return true;
5        return hasPathSum(t.left, sum - t.val )|| hasPathSum(t.right, sum - t.val);
6 }

和同学讨论了一下,我刚开始想的是判断左子树是否为null,不为null就递归左子树,然后再判断右子树,但是发现这样无法确定最后的return语句了。因此在做递归/DFS问题时,关于true或者false的判断一定要在最前面做,后面只是单纯的做函数的循环!这个是DFS代码的技巧,希望一定要记住。


2、Same Tree

题目:

Given two binary trees, write a function to check if they are the same or not.

Two binary trees are considered the same if they are structurally identical and the nodes have the same value.

Example 1:

Input:     1         1
          / \       / \
         2   3     2   3

        [1,2,3],   [1,2,3]

Output: true

Example 2:

Input:     1         1
          /           \
         2             2

        [1,2],     [1,null,2]

Output: false

Example 3:

Input:     1         1
          / \       / \
         2   1     1   2

        [1,2,1],   [1,1,2]

Output: false

分析:这个题是要求我们判断两个数是否完全相等,当然可以从两个角度来做,一个是BFS,一个是DFS。

BFS的话,就是遍历每一层,使用非递归的方法,大体思路要用Queue来实现,具体代码如下:

 1     public boolean isSameTree(TreeNode p, TreeNode q) {
 2 
 3         //BFS版本,用非递归实现。代码量比较冗长
 4         Queue<TreeNode> queue1 = new LinkedList<>();
 5         Queue<TreeNode> queue2 = new LinkedList<>();
 6 
 7         if ( p == null && q == null ) return true;
 8         if ( p == null || q == null ) return false;
 9         queue1.offer(p);
10         queue2.offer(q);
11 
12         while ( queue1.size() > 0 && queue2.size() > 0 ){
13             TreeNode t1 = queue1.poll();
14             TreeNode t2 = queue2.poll();
15             if ( t1.val != t2.val ) return false;
16             if ( t1.left != null && t2.left != null ){
17                 queue1.offer(t1.left);
18                 queue2.offer(t2.left);
19             }
20             if ( t1.left == null && t2.left != null ) return false;
21             if ( t1.left != null && t2.left == null ) return false;
22 
23             if ( t1.right != null && t2.right != null ){
24                 queue1.offer(t1.right);
25                 queue2.offer(t2.right);
26             }
27             if ( t1.right == null && t2.right != null ) return false;
28             if ( t1.right != null && t2.right == null ) return false;
29         }
30         return true;
31 }

可以看到用BFS出现了大量的代码重用,多余空间,效率确实不高,在leetcode上运行需要6ms,主要问题就是不简洁,可读性不高

那么用DFS来实现就简单的多,因为使用递归,所以代码很简洁。DFS使用一定要注意只关注当前状态而不去考虑之前或者之后的状态。这个理论在判断递归结束条件的时候非常有用。在本题中,判断true的条件就是搜索到叶子节点,代码如下:

1 public boolean isSameTree(TreeNode p, TreeNode q) {
2     if ( p == null && q == null ) return true;
3     if ( p == null || q == null ) return false;
4     if ( p.val != q.val ) return false;
5     return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
6 }

注意,这里return true并不是返回最后的结果,只是返回当前状态对应的状态结果。


3、Minmum Depth of Binary Tree

题目:

Given a binary tree, find its minimum depth.

The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node.

Note: A leaf is a node with no children.

Example:

Given binary tree [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7

return its minimum depth = 2.

分析:求二叉树的最小高度,显然用DFS来做。分析过程如下:

这里理解了一下递归的思想,递归是将大问题不断转化成小的问题,关键是找到递归结束条件和递归时机。代码如下:

 1     public int minDepth(TreeNode root) {
 2         if ( root == null ) return 0;
 3         return DFS(root);
 4     }
 5     public int DFS(TreeNode root) {
 6         if ( root.left == null && root.right == null ) return 1;   //找到一个叶子节点,那么叶子节点就是1层
 7         if ( root.left == null ) {
 8             return DFS(root.right) + 1;
 9         }
10         if ( root.right == null ) {
11             return DFS(root.left) + 1;
12         }
13         return Math.min(DFS(root.left), DFS(root.right)) + 1;
14     }

猜你喜欢

转载自www.cnblogs.com/boris1221/p/9222046.html