LeetCode中的数据结构2:二叉树

二叉树具有天然的递归性,二叉树问题也常用递归方式求解。递归函数应该包含两部分:递归终止条件和递归过程。
LeetCode 104 Maximum Depth of Binary Tree,求二叉树的最大深度,就是使用递归方法求解的非常简单的二叉树问题。

public int maxDepth(TreeNode root) {
	// 递归终止条件
    if (root == null) {
        return 0;
    }
    // 递归过程
    return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
}

LeetCode 226 Invert Binary Tree是知名血案问题,因为Max Howell(Homebrew的作者)因为没有解出这道题被Google拒绝。

public TreeNode invertTree(TreeNode root) {
    if(root == null) {
        return null;
    }
    TreeNode newRight = invertTree(root.left);
    TreeNode newLeft = invertTree(root.right);
    root.left = newLeft;
    root.right = newRight;
    return root;
}

还有很多类似的问题,例如LeetCode 100、101
100 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.

public boolean isSameTree(TreeNode p, TreeNode q) {
    if (p==null && q==null) {
        return true;
    }
    if (p==null || q==null) {
        return false;
    }
    Queue<TreeNode> queue1 = new LinkedList<TreeNode>();
    queue1.offer(p);
    Queue<TreeNode> queue2 = new LinkedList<TreeNode>();
    queue2.offer(q);
    while (!queue1.isEmpty() && !queue2.isEmpty()) {
        TreeNode node1 = queue1.poll();
        TreeNode node2 = queue2.poll();
        if (node1.val != node2.val) {
            return false;
        }
        if (node1.left != null && node2.left != null) {
            queue1.offer(node1.left);
            queue2.offer(node2.left);
        } else if (node1.left != null || node2.left != null) {
            return false;
        }
        if (node1.right != null && node2.right != null) {
            queue1.offer(node1.right);
            queue2.offer(node2.right);
        } else if (node1.right != null || node2.right != null) {
            return false;
        }        
    }
    if (!queue1.isEmpty() || !queue2.isEmpty()) {
        return false;
    }
    return true;
}

101 Symmetric Tree

public boolean isSymmetric(TreeNode root) {
    if(root == null) {
        return true;
    }
    return isMirror(root.left, root.right);
}
private boolean isMirror(TreeNode node1, TreeNode node2) {
    if (node1 == null && node2 == null) {
        return true;
    }
    if (node1 == null || node2 == null) {
        return false;
    }
    return node1.val == node2. val 
        && isMirror(node1.left, node2.right)
        && isMirror(node1.right, node2.left);
}

LeetCode 222 Count Complete Tree Nodes,Given a complete binary tree, count the number of nodes.给定一棵完全二叉树,求完全二叉树的节点个数。其中完全二叉树是指:除了最后一层,所有层的节点数达到最大,与此同时,最后一层的所有节点都在最左边。但是我的解法并没有用到完全二叉树的性质,而是前序遍历整棵二叉树,数了节点个数,所以这道题有更好的解法待探究。

class Solution {
    int count = 0;
    public int countNodes(TreeNode root) {
        preOrder(root);
        return count;
    }
    public void preOrder(TreeNode root) {
        if (root ==null) {
            return;
        }
        count++;
        preOrder(root.left);
        preOrder(root.right);
    }
}

LeetCode 110 Balanced Binary Tree,Given a binary tree, determine if it is height-balanced. For this problem, a height-balanced binary tree is defined as: a binary tree in which the depth of the two subtrees of every node never differ by more than 1.判断一棵二叉树是否为平衡二叉树。平衡二叉树的定义是,每一个几点的左右子树的高度差不能超过1。

public boolean isBalanced(TreeNode root) {
    if (root == null) {
        return true;
    }
    if (Math.abs(longPath(root.left)-longPath(root.right))>1) {
        return false;
    }
    return isBalanced(root.left) && isBalanced(root.right);       
}
private int longPath(TreeNode root) {
    if (root==null) {
        return 0;
    }
    return Math.max(longPath(root.left), longPath(root.right))+1;
}

完成正确的递归函数的关键之一就是找到递归终止条件。上面几道题目的递归终止条件都很简单,看下一下几道题目。
LeetCode 112 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. 给出一棵二叉树以及一个数字sum,判断在这棵二叉树上是否存在一条从根到叶子的路径,其路径上的所有节点和为sum。注意是从根到叶子节点。

public boolean hasPathSum(TreeNode root, int sum) {
    if (root == null) {
        return false;
    }
    if (isLeaf(root)) {
        return sum==root.val;
    }
    return hasPathSum(root.left, sum-root.val) || hasPathSum(root.right, sum-root.val);
}    
private boolean isLeaf(TreeNode node) {
    if (node == null) {
        return false;
    } 
    return node.left == null && node.right == null;
}

LeetCode 111 Minimum Depth of Binary Tree, Given a binary tree, find its minimum depth. 求一棵二叉树的最低深度

public int minDepth(TreeNode root) {
    if (root == null) {
        return 0;
    }
    if (!isLeaf(root) && root.left == null) {
        return minDepth(root.right)+1;
    }
    if (!isLeaf(root) && root.right == null) {
        return minDepth(root.left)+1;
    }
    return Math.min(minDepth(root.left), minDepth(root.right))+1;
}

private boolean isLeaf(TreeNode node) {
    if (node == null) {
        return false;
    } 
    return node.left==null && node.right==null;
}

LeetCode 404 Sum of Left Leaves, Find the sum of all left leaves in a given binary tree. 求一个二叉树所有左叶子的和。

class Solution {
    int sum = 0;
    public int sumOfLeftLeaves(TreeNode root) {
        if (root == null) {
            return sum;
        }
        if (isLeaf(root.left)) {
            sum += root.left.val;
        }
        sumOfLeftLeaves(root.left);
        sumOfLeftLeaves(root.right);
        return sum;
    }
    
    private boolean isLeaf(TreeNode node) {
        if (node == null) {
            return false;
        } 
        return node.left == null && node.right==null;
    }
}

在看几道递归逻辑复杂一些的。
LeetCode 257 Binary Tree Paths, Given a binary tree, return all root-to-leaf paths. 给定一棵二叉树,返回所有变是从根节点到叶子节点路径的字符串。

class Solution {
    List<String> res = new ArrayList<>();
    public List<String> binaryTreePaths(TreeNode root) {
        if (root == null) {
            return res;
        }
        String s = "";
        findPath(s, root);
        return res;       
    }
    private void findPath(String s, TreeNode root) {
        s += (root.val + "->");
        if (root.left == null && root.right==null) {
            s=s.substring(0, s.length()-2);
            res.add(s);
            return;
        }
        if (root.left != null) {
            String s1 = new String(s);
            findPath(s1, root.left);
        }
        if (root.right != null) {
            String s2 = new String(s);
            findPath(s2, root.right);
        }       
    }
}

LeetCode 113 Path Sum II, Given a binary tree and a sum, find all root-to-leaf paths where each path’s sum equals the given sum. 给定一棵二叉树,返回所有从根节点到叶子节点的和为sum的路径。

class Solution {
    List<List<Integer>> res = new ArrayList<>();
    public List<List<Integer>> pathSum(TreeNode root, int sum) {
        if (root == null) {
            return res;
        }
        List<Integer> list = new ArrayList<>();
        pathSum(list, root, sum);
        return res;
    }
    private void pathSum(List<Integer> list, TreeNode root, int sum) {
        list.add(root.val);
        if (root.left == null && root.right==null && sum==root.val) {
            List<Integer> list1 = copyArrayList(list);
            res.add(list1);
            return;
        }
        if (root.left != null) {
            List<Integer> list1 = copyArrayList(list);
            pathSum(list1, root.left, sum-root.val);
        }
        if (root.right != null) {
            List<Integer> list1 = copyArrayList(list);
            pathSum(list1, root.right, sum-root.val);
        }
    }
    
    private ArrayList<Integer> copyArrayList(List<Integer> list) {
        ArrayList<Integer> copy = new ArrayList<>(Arrays.asList(new Integer[list.size()]));
        for (int i=0; i<list.size(); i++) {
            copy.set(i, list.get(i));
        }
        return copy;
    }
}

LeetCode 129 Sum Root to Leaf Numbers, Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number. An example is the root-to-leaf path 1->2->3 which represents the number 123. Find the total sum of all root-to-leaf numbers. 给定一棵二叉树,每个节点只包含数字0-9,从根节点到叶子节点的每条路径可以表示成一个数,请这些数的和。例如从根节点到叶子节点分别为1->2->3,那么这条路径代表数字123。求所有路径代表的数字的和。

class Solution {
    List<List<Integer>> res = new ArrayList<>();
    public int sumNumbers(TreeNode root) {
        if (root == null) {
            return 0;
        }
        List<Integer> list = new ArrayList<>();
        findPath(root, list);
        Integer ans = 0;
        for (int i=0; i<res.size(); i++) {
            List<Integer> listTemp = res.get(i);
            Integer ansTemp = 0;
            for (int j=0; j<listTemp.size(); j++) {
                ansTemp += listTemp.get(j)*(int)(Math.pow(10, (listTemp.size()-j-1)));
            }
            ans += ansTemp;
        }
        return ans;
    }
    private void findPath(TreeNode root, List<Integer> list) {
        list.add(root.val);
        if (root.left == null && root.right == null) {
            List<Integer> copy = copyArrayList(list);
            res.add(copy);
            return;
        }
        if (root.left != null) {
            List<Integer> copy = copyArrayList(list);
            findPath(root.left, copy);
        } 
        if (root.right != null) {
            List<Integer> copy = copyArrayList(list);
            findPath(root.right, copy);
        }
    }
    private List<Integer> copyArrayList(List<Integer> list) {
        List<Integer> copy = new ArrayList<>(Arrays.asList(new Integer[list.size()]));
        for (int i=0; i<list.size(); i++) {
            copy.set(i, list.get(i));
        }
        return copy;
    }
}

上面都是普通二叉树涉及的算法,二叉树中有一类非常特殊的二叉树:二分搜索树。对于一棵二分搜索树,每个节点的键值大于左孩子,每个节点的键值小于右孩子,以左右孩子为根的子树仍未二分搜索树。
LeetCode 235 Lowest Common Ancestor of a Binary Search Tree, Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST. 给定一棵二分搜索树和两个节点,寻找这两个节点的最近公共祖先。

public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
    if (root == null || p == null || q == null) {
        return null;
    }
    if (root.val>p.val && root.val>q.val) {
        return lowestCommonAncestor(root.left, p, q);
    }
    if (root.val<p.val && root.val<q.val) {
        return lowestCommonAncestor(root.right, p, q);
    }
    return root;
}

还有236题,在普通二叉树中寻找两个节点的最近公共祖先。
二分搜索树的经典题目还有:98、450、108、230,会陆续完善。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章