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

二叉树具有天然的递归性,二叉树问题也常用递归方式求解。递归函数应该包含两部分:递归终止条件和递归过程。例如求二叉树的最大深度,就是使用递归方法求解的非常简单的二叉树问题。
LeetCode 104 Maximum Depth of Binary Tree
https://leetcode.com/problems/maximum-depth-of-binary-tree/
Given a binary tree, find its maximum depth. The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node.

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
https://leetcode.com/problems/invert-binary-tree/
Invert a binary tree. 翻转二叉树。

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 Same Tree
https://leetcode.com/problems/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;
        }
        if (p.val == q.val) {
            return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
        }
        return false;
}

LeetCode 101 Symmetric Tree
https://leetcode.com/problems/symmetric-tree/
Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center).

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
https://leetcode.com/problems/count-complete-tree-nodes
Given a complete binary tree, count the number of nodes. 给定一棵完全二叉树,求完全二叉树的节点个数。其中完全二叉树是指:除了最后一层,所有层的节点数达到最大,与此同时,最后一层的所有节点都在最左边。但是我的解法并没有用到完全二叉树的性质,直接数了节点个数。但是结果还不错:Runtime: 0 ms, faster than 100.00% of Java online submissions. Memory Usage: 38.8 MB, less than 97.58% of Java online submissions. 这道题可能有更好的解法待探究。

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

LeetCode 110 Balanced Binary Tree
https://leetcode.com/problems/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
https://leetcode.com/problems/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
https://leetcode.com/problems/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
https://leetcode.com/problems/sum-of-left-leaves
Find the sum of all left leaves in a given binary tree. 求一个二叉树所有左叶子的和。

class Solution {
    public int sumOfLeftLeaves(TreeNode root) {
        return sumOfLeftLeaves(root, 0);
    }
    
    private int sumOfLeftLeaves(TreeNode root, int isLeft) {
        if (root == null) {
            return 0;
        }                     
        return root.val*isLeft*isLeaf(root) + sumOfLeftLeaves(root.left, 1) + sumOfLeftLeaves(root.right, 0);
    }
    
    private int isLeaf(TreeNode root) {
        if (root == null) {
            return 0;
        }
        if (root.left == null && root.right == null) {
            return 1;
        }
        return 0;
    }
}

再看几道递归逻辑复杂一些的。
LeetCode 257 Binary Tree Paths
https://leetcode.com/problems/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
https://leetcode.com/problems/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
https://leetcode.com/problems/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
https://leetcode.com/problems/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题,在普通二叉树中寻找两个节点的最近公共祖先。
二分搜索树的经典题目还有:
LeetCode 98 Validate Binary Search Tree
https://leetcode.com/problems/validate-binary-search-tree/
Given a binary tree, determine if it is a valid binary search tree (BST).

public boolean helper(TreeNode node, Integer lower, Integer upper) {
        if (node == null) return true;
        int val = node.val;
        if (lower != null && val <= lower) return false;
        if (upper != null && val >= upper) return false;
        return helper(node.right, val, upper) && helper(node.left, lower, val);
        
    }
    public boolean isValidBST(TreeNode root) {
        return helper(root, null, null);
    }

LeetCode 450 Delete Node in a BST
https://leetcode.com/problems/delete-node-in-a-bst
Given a root node reference of a BST and a key, delete the node with the given key in the BST. Return the root node reference (possibly updated) of the BST.

public TreeNode deleteNode(TreeNode root, int key) {
    if (root == null) {
        return null;
    }
    if (root.val == key) {
        if (root.left == null) {
            return root.right;
        }
        if (root.right == null) {
            return root.left;
        }
        TreeNode temp = findMin(root.right);
        root.right = deleteNode(root.right, temp.val);
        temp.right = root.right;
        temp.left = root.left;
        return temp;
    }
    if (root.val > key) {
        root.left = deleteNode(root.left, key);
    } 
    if (root.val < key) {
        root.right = deleteNode(root.right, key);
    } 
    return root;
}
private TreeNode findMin(TreeNode root) {
    if (root == null) {
        return null;
    }
    if (root.left == null) {
        return root;
    }
    return findMin(root.left);
}

LeetCode 108 Convert Sorted Array to Binary Search Tree
https://leetcode.com/problems/convert-sorted-array-to-binary-search-tree
Given an array where elements are sorted in ascending order, convert it to a height balanced BST. 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.

LeetCode 230 Kth Smallest Element in a BST
https://leetcode.com/problems/kth-smallest-element-in-a-bst
Given a binary search tree, write a function kth Smallest to find the kth smallest element in it.

class Solution {
    int c = 0;
    int ans = 0;
    public int kthSmallest(TreeNode root, int k) {
        if (root == null) {
            return ans;
        }
        ans = kthSmallest(root.left, k);
        c++;
        if (c==k) {
            return root.val;
        }
        ans = kthSmallest(root.right, k);
        return ans;
    }
}

LeetCode 236 Lowest Common Ancestor of a Binary Tree
Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.

class Solution {
    private TreeNode res = null;
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        recurseTree(root, p, q);
        return res;
        
    }
    
    private boolean recurseTree(TreeNode root, TreeNode p, TreeNode q) {
        if (root == null) {
            return false;
        }
        int left = recurseTree(root.left, p, q) ? 1 : 0;
        int right = recurseTree(root.right, p, q) ? 1 : 0;
        int mid = (root == p || root == q) ? 1 : 0;
        
        if (left + right +mid >= 2) {
            res = root;
        }
        return mid+left+right>0;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章