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;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章