1. 程式人生 > 實用技巧 >Leetcode(easy Tree)

Leetcode(easy Tree)

Leetcode(easy Tree)

leetcode 簡單的樹的題目,記錄一下自己的刷題過程

100. 相同的樹

給定兩個二叉樹,編寫一個函式來檢驗它們是否相同。
如果兩個樹在結構上相同,並且節點具有相同的值,則認為它們是相同的。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean isSameTree(TreeNode p, TreeNode q) {
        // myidea : 採用遞迴 比較當前傳入的節點是否相同,如果相同,就繼續遞迴遍歷其右子樹與左子樹
        // 遞迴出口:如果傳入的兩個節點均不存在,則返回true,若其中一個為空,另外一個不為空,則返回false
        if(p == null && q == null) return true;
        if(p == null || q == null) return false;
        // 兩者皆不為空,遞迴判斷兩者的左子樹與兩者的右子樹
        return (p.val == q.val) && isSameTree(p.left,q.left) && isSameTree(p.right,q.right);
        
    }
}

101. 對稱二叉樹

給定一個二叉樹,檢查它是否是映象對稱的。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean isSymmetric(TreeNode root) {
        // myidea: 也是採用遞迴,用一個額外的輔助函式,來進行判斷
        return helper(root,root);
        
    }
    // 輔助函式,傳入的引數為根節點,然後遞迴依次判斷root1的左子樹與root2的右子樹是否相同
    public boolean helper(TreeNode root1,TreeNode root2){
        // 遞迴出口
        // 如果傳入的兩個樹節點均不存在肯定是true
        if(root1 == null && root2 == null) return true;
        // 如果只有一個不存在,那麼肯定是錯誤的 返回false
        if(root1 == null || root2 == null) return false;
        // 判斷傳入的樹節點的值是否相同 遞迴判斷root1的左子樹與root2的右子樹,以及root1的右子樹與root2的左子樹是否相同
        return (root1.val == root2.val) && helper(root1.left,root2.right) && helper(root1.right,root2.left);

    }
}

104. 二叉樹的最大深度

給定一個二叉樹,找出其最大深度。
二叉樹的深度為根節點到最遠葉子節點的最長路徑上的節點數。
說明: 葉子節點是指沒有子節點的節點。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public int maxDepth(TreeNode root) {
        // myidea:採用遞迴
        // 遞迴出口:
        if(root == null) return 0;
        // 遞迴體
        return Math.max(maxDepth(root.left),maxDepth(root.right))+1;
    }
}

107. 二叉樹的層次遍歷 II

給定一個二叉樹,返回其節點值自底向上的層次遍歷。 (即按從葉子節點所在層到根節點所在的層,逐層從左向右遍歷)

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<List<Integer>> levelOrderBottom(TreeNode root) {
        // myidea: 層次遍歷麼,很簡單就是採用佇列的方式進行就好了,首先先計算出來整個樹的最大深度,然後記錄為flag,每次倒著更新res就可以了
        List<List<Integer>> res = new ArrayList<List<Integer>>();
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        // 如果root為空的話
        if(root == null) return res;
        int flag = depth(root)-1;
        for(int i = 0;i<=flag;i++) res.add(new ArrayList<Integer>());
        queue.offer(root);
        while(!queue.isEmpty()){
            int size = queue.size();
            for(int i = 0;i<size;i++){
                TreeNode tmp = queue.poll();
                res.get(flag).add(tmp.val);
                if(tmp.left != null) queue.offer(tmp.left);
                if(tmp.right != null) queue.offer(tmp.right);
            }
            flag--;
        }
        return res;

    }
    // 返回一個樹的最大深度
    public int depth(TreeNode root){
        if(root == null) return 0;
        return Math.max(depth(root.left),depth(root.right))+1;
    }
}

108. 將有序陣列轉換為二叉搜尋樹

將一個按照升序排列的有序陣列,轉換為一棵高度平衡二叉搜尋樹。
本題中,一個高度平衡二叉樹是指一個二叉樹每個節點 的左右兩個子樹的高度差的絕對值不超過 1。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode sortedArrayToBST(int[] nums) {
        return helper(nums,0,nums.length-1);
    }
    public TreeNode helper(int[] nums,int left,int right){
        if(left>right) return null;
        int mid = (left+right)/2;
        TreeNode root = new TreeNode(nums[mid]);
        root.left = helper(nums,left,mid-1);
        root.right = helper(nums,mid+1,right);
        return root;
    }
}

110. 平衡二叉樹

給定一個二叉樹,判斷它是否是高度平衡的二叉樹。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean isBalanced(TreeNode root) {
        if(root==null) return true;
        return Math.abs(depth(root.left)-depth(root.right))<2 && isBalanced(root.left) && isBalanced(root.right);
    }
    public int depth(TreeNode root){
        if(root==null) return 0;
        return Math.max(depth(root.left),depth(root.right)) + 1;
    }
}

111. 二叉樹的最小深度

給定一個二叉樹,找出其最小深度。
最小深度是從根節點到最近葉子節點的最短路徑上的節點數量。
說明:葉子節點是指沒有子節點的節點。


112. 路徑總和

給定一個二叉樹和一個目標和,判斷該樹中是否存在根節點到葉子節點的路徑,這條路徑上所有節點值相加等於目標和。
說明: 葉子節點是指沒有子節點的節點。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    boolean vaild;
    int pathSum;
    public boolean hasPathSum(TreeNode root, int sum) {
        // myidea : 採用遞迴+回溯
        if(root == null) return false;
        vaild = false;
        pathSum = 0;
        dfs(root,sum,pathSum);
        return vaild;

    }
    public void dfs(TreeNode root,int sum,int pathSum){
        // 遞迴出口
        if(root !=null && sum == pathSum + root.val && root.left == null && root.right == null){
            vaild = true;
            return;
        }
        if(root == null) return;
        // 遞迴
        dfs(root.left,sum,pathSum+root.val);
        dfs(root.right,sum,pathSum+root.val);
        // 回溯
        pathSum-=root.val;
        return;
    }
}

226. 翻轉二叉樹

翻轉一棵二叉樹。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode invertTree(TreeNode root) {
        // myidea:遞迴
        if(root == null) return root;
        TreeNode left = invertTree(root.left);
        TreeNode right = invertTree(root.right);
        root.left = right;
        root.right = left;
        return root;
    }

}

235. 二叉搜尋樹的最近公共祖先

給定一個二叉搜尋樹, 找到該樹中兩個指定節點的最近公共祖先。
百度百科中最近公共祖先的定義為:“對於有根樹 T 的兩個結點 p、q,最近公共祖先表示為一個結點 x,滿足 x 是 p、q 的祖先且 x 的深度儘可能大(一個節點也可以是它自己的祖先)。”

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */

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

257. 二叉樹的所有路徑

給定一個二叉樹,返回所有從根節點到葉子節點的路徑。
說明: 葉子節點是指沒有子節點的節點。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    List<String> res;
    public List<String> binaryTreePaths(TreeNode root) {
        // myidea:用遞迴+回溯即可 
        res = new LinkedList<String>();
        dfs(root,"");
        return res;

    }
    public void dfs(TreeNode node,String str){
        if(node == null) return;
        // 到達葉子節點
        if(node.left == null && node.right == null){
            str = str + node.val;
            res.add(str);
            return;
        }
        String tmp = str;
        str = str + node.val + "->";
        // 沒有到達葉子節點,就遍歷其兒子節點
        dfs(node.left,str);
        dfs(node.right,str);
        // 回溯
        str = tmp;
    }
}

404. 左葉子之和

計算給定二叉樹的所有左葉子之和。


/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    int res = 0;
    public int sumOfLeftLeaves(TreeNode root) {
        // myidea:遞迴+回溯
        dfs(root,0);
        return res;
    }
    // flag 標記位,1表示是左兒子,2表示右兒子
    public void dfs(TreeNode node,int flag){
        if(node == null) return;
        if(node.left == null && node.right == null){
            if(flag == 1) res+=node.val;
            return;
        }
        dfs(node.left,1);
        dfs(node.right,2);
    }
}

501. 二叉搜尋樹中的眾數


/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    Map<Integer,Integer> map;
    public int[] findMode(TreeNode root) {
        // myidea:最簡單的想法就是採用層次遍歷,或者前,中,後序遍歷,用map記錄
        // 但是題目中的進階不讓使用額外的空間,這時候就需要考慮二叉搜尋樹的結構性質了
        // 首先先實現O(n)額外空間的實現方法
        map = new HashMap<Integer,Integer>();
        List<Integer> list = new ArrayList<Integer>();
        preOrder(root);
        int max = Integer.MIN_VALUE;
        // 找到最多數字出現的次數
        for(int key:map.keySet()) if(map.get(key) > max) max = map.get(key);
        for(int key:map.keySet()) if(map.get(key) == max) list.add(key);
        int[] res = new int[list.size()];
        for(int i = 0;i<list.size();i++) res[i] = list.get(i);
        return res;



    }
    public void preOrder(TreeNode node){
        if(node == null) return;
        if(!map.containsKey(node.val)) map.put(node.val,0);
        map.put(node.val,map.get(node.val)+1);
        preOrder(node.left);
        preOrder(node.right);

    }
}

530. 二叉搜尋樹的最小絕對差

給你一棵所有節點為非負值的二叉搜尋樹,請你計算樹中任意兩節點的差的絕對值的最小值。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    List<Integer> record = new ArrayList<Integer>();
    public int getMinimumDifference(TreeNode root) {
        // myidea 二叉搜尋樹的中序遍歷是一個有序陣列
        inOrder(root);
        int res = Integer.MAX_VALUE;
        for(int i = 0;i<record.size()-1;i++) res = Math.min(res,record.get(i+1) - record.get(i));
        return res;

    }
    public void inOrder(TreeNode root){
        if(root == null) return;
        inOrder(root.left);
        record.add(root.val);
        inOrder(root.right);
    }
}

543. 二叉樹的直徑

給定一棵二叉樹,你需要計算它的直徑長度。一棵二叉樹的直徑長度是任意兩個結點路徑長度中的最大值。這條路徑可能穿過也可能不穿過根結點。


/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public int diameterOfBinaryTree(TreeNode root) {
        // myidea 不就是根的左子樹的高度與根的右子樹的高度之和麼?
        // 注意題目中說了 這個路徑 可能穿過跟節點 也可能不穿過跟節點
        if(root == null) return 0;
        int res = Math.max((depth(root.left) + depth(root.right)),diameterOfBinaryTree(root.left));
        return Math.max(res,diameterOfBinaryTree(root.right));
    }
    public int depth(TreeNode root){
        if(root == null) return 0;
        return Math.max(depth(root.left) , depth(root.right))+1;
    }
}

559. N叉樹的最大深度

給定一個 N 叉樹,找到其最大深度。
最大深度是指從根節點到最遠葉子節點的最長路徑上的節點總數。

/*
// Definition for a Node.
class Node {
    public int val;
    public List<Node> children;

    public Node() {}

    public Node(int _val) {
        val = _val;
    }

    public Node(int _val, List<Node> _children) {
        val = _val;
        children = _children;
    }
};
*/

class Solution {
    public int maxDepth(Node root) {
        // myidea 採用層次遍歷
        if(root == null) return 0;
        Queue<Node> queue = new LinkedList<Node>();
        int depth = 0;
        queue.offer(root);
        while(!queue.isEmpty()){
            depth++;
            int size = queue.size();
            for(int i = 0;i<size;i++){
                Node node = queue.poll();
                for(Node child:node.children) queue.offer(child);
            }
        }
        return depth;
        
    }
}

563. 二叉樹的坡度

給定一個二叉樹,計算 整個樹 的坡度 。
一個樹的 節點的坡度 定義即為,該節點左子樹的節點之和和右子樹節點之和的 差的絕對值 。如果沒有左子樹的話,左子樹的節點之和為 0 ;沒有右子樹的話也是一樣。空結點的坡度是 0 。
整個樹 的坡度就是其所有節點的坡度之和。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    List<Integer> list = new ArrayList<Integer>();
    public int findTilt(TreeNode root) {
        // myidea:藉助一個輔助list,記錄每次左右子樹的和的差值,然後利用dfs進行遍歷
        if(root == null) return 0;
        calSum(root);
        int res = 0;
        for(int num:list) res+=num;
        return res;

    }
    // 計算整個樹的和
    public int calSum(TreeNode root){
        if(root == null) return 0;
        int left = calSum(root.left);
        int right = calSum(root.right);
        list.add(Math.abs(left-right));
        return left+right+root.val;
    }
}

572. 另一個樹的子樹

給定兩個非空二叉樹 s 和 t,檢驗 s 中是否包含和 t 具有相同結構和節點值的子樹。s 的一個子樹包括 s 的一個節點和這個節點的所有子孫。s 也可以看做它自身的一棵子樹。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean isSubtree(TreeNode s, TreeNode t) {
        if(t == null) return true;
        if(s == null) return false;
        return isSame(s,t) || isSubtree(s.left,t) || isSubtree(s.right,t);
        
    }
    // 判斷兩棵樹是否相同
    public boolean isSame(TreeNode s,TreeNode t){
        if(s == null && t == null) return true;
        if(s == null || t == null) return false;
        return (s.val == t.val) && isSame(s.left,t.left) && isSame(s.right,t.right); 
    }
}

589. N叉樹的前序遍歷

給定一個 N 叉樹,返回其節點值的前序遍歷。

/*
// Definition for a Node.
class Node {
    public int val;
    public List<Node> children;

    public Node() {}

    public Node(int _val) {
        val = _val;
    }

    public Node(int _val, List<Node> _children) {
        val = _val;
        children = _children;
    }
};
*/

class Solution {
    List<Integer> res = new ArrayList<Integer>();
    public List<Integer> preorder(Node root) {
        //myidea : 採用深度遍歷的思想,就可以了
        if(root == null) return res;
        dfs(root);
        return res;
        
    }
    // 深度遍歷
    public void dfs(Node root){
        if(root == null) return;
        res.add(root.val);
        for(Node child:root.children) dfs(child);
    }
}
// 採用迭代法
class Solution {
    public List<Integer> preorder(Node root) {
        // myidea:如果使用迭代法的話,需要使用額外的資料結構,這裡使用額外的棧資料結構,
        Stack<Node> stack = new Stack<>();
        List<Integer> res = new LinkedList<>();
        if (root == null) {
            return res;
        }
        stack.push(root);
        while (!stack.isEmpty()) {
            Node node = stack.pop();
            res.add(node.val);
            // 將該節點所有的兒子從右到左壓入棧中
            Collections.reverse(node.children);
            for (Node item : node.children) {
                stack.push(item);
            }
        }
        return res;
    }
}

590. N叉樹的後序遍歷

給定一個 N 叉樹,返回其節點值的後序遍歷。

/*
// Definition for a Node.
class Node {
    public int val;
    public List<Node> children;

    public Node() {}

    public Node(int _val) {
        val = _val;
    }

    public Node(int _val, List<Node> _children) {
        val = _val;
        children = _children;
    }
};
*/
class Solution {
    public List<Integer> postorder(Node root) {
        Stack<Node> stack = new Stack<>();
        LinkedList<Integer> res = new LinkedList<>();
        if (root == null) {
            return res;
        }

      stack.push(root);
      while (!stack.isEmpty()) {
          Node node = stack.pop();
          res.addFirst(node.val);
          for (Node item : node.children) {
              if (item != null) {
                  stack.push(item);    
              } 
          }
      }
      return res;
    }
}

606. 根據二叉樹建立字串

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public String tree2str(TreeNode t) {
        if(t==null)
            return "";
        if(t.left==null && t.right==null)
            return t.val+"";
        if(t.right==null)
            return t.val+"("+tree2str(t.left)+")";
        return t.val+"("+tree2str(t.left)+")("+tree2str(t.right)+")";   
    }
}

617. 合併二叉樹

給定兩個二叉樹,想象當你將它們中的一個覆蓋到另一個上時,兩個二叉樹的一些節點便會重疊。
你需要將他們合併為一個新的二叉樹。合併的規則是如果兩個節點重疊,那麼將他們的值相加作為節點合併後的新值,否則不為 NULL 的節點將直接作為新二叉樹的節點。

class Solution {
    public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
        if (t1 == null) {
            return t2;
        }
        if (t2 == null) {
            return t1;
        }
        TreeNode merged = new TreeNode(t1.val + t2.val);
        merged.left = mergeTrees(t1.left, t2.left);
        merged.right = mergeTrees(t1.right, t2.right);
        return merged;
    }
}

637. 二叉樹的層平均值

給定一個非空二叉樹, 返回一個由每層節點平均值組成的陣列。

class Solution {
    public List<Double> averageOfLevels(TreeNode root) {
        List<Double> averages = new ArrayList<Double>();
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            double sum = 0;
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                TreeNode node = queue.poll();
                sum += node.val;
                TreeNode left = node.left, right = node.right;
                if (left != null) {
                    queue.offer(left);
                }
                if (right != null) {
                    queue.offer(right);
                }
            }
            averages.add(sum / size);
        }
        return averages;
    }
}

653. 兩數之和 IV - 輸入 BST

給定一個二叉搜尋樹和一個目標結果,如果 BST 中存在兩個元素且它們的和等於給定的目標結果,則返回 true。

public class Solution {
    public boolean findTarget(TreeNode root, int k) {
        List < Integer > list = new ArrayList();
        inorder(root, list);
        int l = 0, r = list.size() - 1;
        while (l < r) {
            int sum = list.get(l) + list.get(r);
            if (sum == k)
                return true;
            if (sum < k)
                l++;
            else
                r--;
        }
        return false;
    }
    public void inorder(TreeNode root, List < Integer > list) {
        if (root == null)
            return;
        inorder(root.left, list);
        list.add(root.val);
        inorder(root.right, list);
    }
}

669. 修剪二叉搜尋樹

給你二叉搜尋樹的根節點 root ,同時給定最小邊界low 和最大邊界 high。通過修剪二叉搜尋樹,使得所有節點的值在[low, high]中。修剪樹不應該改變保留在樹中的元素的相對結構(即,如果沒有被移除,原有的父代子代關係都應當保留)。 可以證明,存在唯一的答案。
所以結果應當返回修剪好的二叉搜尋樹的新的根節點。注意,根節點可能會根據給定的邊界發生改變。

class Solution {
    public TreeNode trimBST(TreeNode root, int L, int R) {
        if (root == null) return root;
        if (root.val > R) return trimBST(root.left, L, R);
        if (root.val < L) return trimBST(root.right, L, R);

        root.left = trimBST(root.left, L, R);
        root.right = trimBST(root.right, L, R);
        return root;
    }
}

671. 二叉樹中第二小的節點

給定一個非空特殊的二叉樹,每個節點都是正數,並且每個節點的子節點數量只能為 2 或 0。如果一個節點有兩個子節點的話,那麼該節點的值等於兩個子節點中較小的一個。
更正式地說,root.val = min(root.left.val, root.right.val) 總成立。
給出這樣的一個二叉樹,你需要輸出所有節點中的第二小的值。如果第二小的值不存在的話,輸出 -1 。

public int findSecondMinimumValue(TreeNode root) {
        if(root == null)
            return -1;
        return find(root, root.val);
    }

    /**
     * 按照題目描述
     * 找到和rootValue值不相同的最小值,與rootValue不相同的最小值其實就是第二小的值。
     */
    private int find(TreeNode x, int rootValue){
        if(x.val != rootValue) // 如果當前結點不等於根結點至,那麼當x值為以x為根的最小的非rootValue的值
            return x.val;
        // 這之下都是 當前結點值為根結點值的情況
        if(x.left == null) // 遞迴到葉子結點 且其值為根結點值,說明沒有找到第二小的值,返回失敗標誌-1。
            return -1;
        int leftMin = find(x.left, rootValue);
        int rightMin = find(x.right, rootValue);
        if(leftMin == -1)
            return rightMin;
        if(rightMin == -1)
            return leftMin;
        return Math.min(leftMin, rightMin);
    }

700. 二叉搜尋樹中的搜尋

給定二叉搜尋樹(BST)的根節點和一個值。 你需要在BST中找到節點值等於給定值的節點。 返回以該節點為根的子樹。 如果節點不存在,則返回 NULL。

class Solution {
  public TreeNode searchBST(TreeNode root, int val) {
    if (root == null || val == root.val) return root;

    return val < root.val ? searchBST(root.left, val) : searchBST(root.right, val);
  }
}

783. 二叉搜尋樹節點最小距離

給定一個二叉搜尋樹的根節點 root,返回樹中任意兩節點的差的最小值。

class Solution {
    Integer prev, ans;
    public int minDiffInBST(TreeNode root) {
        prev = null;
        ans = Integer.MAX_VALUE;
        dfs(root);
        return ans;
    }

    public void dfs(TreeNode node) {
        if (node == null) return;
        dfs(node.left);
        if (prev != null)
            ans = Math.min(ans, node.val - prev);
        prev = node.val;
        dfs(node.right);
    }
}

872. 葉子相似的樹

class Solution {
    public boolean leafSimilar(TreeNode root1, TreeNode root2) {
        List<Integer> leaves1 = new ArrayList();
        List<Integer> leaves2 = new ArrayList();
        dfs(root1, leaves1);
        dfs(root2, leaves2);
        return leaves1.equals(leaves2);
    }

    public void dfs(TreeNode node, List<Integer> leafValues) {
        if (node != null) {
            if (node.left == null && node.right == null)
                leafValues.add(node.val);
            dfs(node.left, leafValues);
            dfs(node.right, leafValues);
        }
    }
}

897. 遞增順序查詢樹

給你一個樹,請你 按中序遍歷 重新排列樹,使樹中最左邊的結點現在是樹的根,並且每個結點沒有左子結點,只有一個右子結點。

class Solution {    
    public TreeNode increasingBST(TreeNode root) {
        List<Integer> vals = new ArrayList();
        inorder(root, vals);
        TreeNode ans = new TreeNode(0), cur = ans;
        for (int v: vals) {
            cur.right = new TreeNode(v);
            cur = cur.right;
        }
        return ans.right;
    }

    public void inorder(TreeNode node, List<Integer> vals) {
        if (node == null) return;
        inorder(node.left, vals);
        vals.add(node.val);
        inorder(node.right, vals);
    }
}

class Solution {
    TreeNode cur;
    public TreeNode increasingBST(TreeNode root) {
        TreeNode ans = new TreeNode(0);
        cur = ans;
        inorder(root);
        return ans.right;
    }

    public void inorder(TreeNode node) {
        if (node == null) return;
        inorder(node.left);
        node.left = null;
        cur.right = node;
        cur = node;
        inorder(node.right);
    }
}

938. 二叉搜尋樹的範圍和

給定二叉搜尋樹的根結點 root,返回 L 和 R(含)之間的所有結點的值的和。
二叉搜尋樹保證具有唯一的值。

class Solution {
    int ans;
    public int rangeSumBST(TreeNode root, int L, int R) {
        ans = 0;
        dfs(root, L, R);
        return ans;
    }

    public void dfs(TreeNode node, int L, int R) {
        if (node != null) {
            if (L <= node.val && node.val <= R)
                ans += node.val;
            if (L < node.val)
                dfs(node.left, L, R);
            if (node.val < R)
                dfs(node.right, L, R);
        }
    
class Solution {
    public int rangeSumBST(TreeNode root, int L, int R) {
        int ans = 0;
        Stack<TreeNode> stack = new Stack();
        stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode node = stack.pop();
            if (node != null) {
                if (L <= node.val && node.val <= R)
                    ans += node.val;
                if (L < node.val)
                    stack.push(node.left);
                if (node.val < R)
                    stack.push(node.right);
            }
        }
        return ans;
    }
}

965. 單值二叉樹

如果二叉樹每個節點都具有相同的值,那麼該二叉樹就是單值二叉樹。
只有給定的樹是單值二叉樹時,才返回 true;否則返回 false。

class Solution {
    List<Integer> vals;
    public boolean isUnivalTree(TreeNode root) {
        vals = new ArrayList();
        dfs(root);
        for (int v: vals)
            if (v != vals.get(0))
                return false;
        return true;
    }

    public void dfs(TreeNode node) {
        if (node != null) {
            vals.add(node.val);
            dfs(node.left);
            dfs(node.right);
        }
    }
}

993. 二叉樹的堂兄弟節點

在二叉樹中,根節點位於深度 0 處,每個深度為 k 的節點的子節點位於深度 k+1 處。
如果二叉樹的兩個節點深度相同,但父節點不同,則它們是一對堂兄弟節點。

class Solution {
    Map<Integer, Integer> depth;
    Map<Integer, TreeNode> parent;

    public boolean isCousins(TreeNode root, int x, int y) {
        depth = new HashMap();
        parent = new HashMap();
        dfs(root, null);
        return (depth.get(x) == depth.get(y) && parent.get(x) != parent.get(y));
    }

    public void dfs(TreeNode node, TreeNode par) {
        if (node != null) {
            depth.put(node.val, par != null ? 1 + depth.get(par.val) : 0);
            parent.put(node.val, par);
            dfs(node.left, node);
            dfs(node.right, node);
        }
    }
}

1022. 從根到葉的二進位制數之和

給出一棵二叉樹,其上每個結點的值都是 0 或 1 。每一條從根到葉的路徑都代表一個從最高有效位開始的二進位制數。例如,如果路徑為 0 -> 1 -> 1 -> 0 -> 1,那麼它表示二進位制數 01101,也就是 13 。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    int ans = 0;    // 存放結果
    int mod = 1000000000 + 7;   // 用作取模
    public int sumRootToLeaf(TreeNode root) {
        helper(root, 0);
        return ans % mod;
    }

    public void helper(TreeNode root, int sum) {
        if (root != null) {      
            sum = sum * 2 + root.val;   
            if (root.left == null && root.right == null) {
                ans += sum;     // 到達葉子節點,得到一個和,加到結果上
            } else {    // 沒有到達葉子節點,繼續遞迴
                helper(root.left, sum);
                helper(root.right, sum);
            }
        }
    }

}

劍指 Offer 27. 二叉樹的映象

請完成一個函式,輸入一個二叉樹,該函式輸出它的映象。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode mirrorTree(TreeNode root) {
        if(root == null) return root;
        TreeNode left = mirrorTree(root.right);
        TreeNode right = mirrorTree(root.left);
        root.left = left;
        root.right = right;
        return root;
    }
}

劍指 Offer 28. 對稱的二叉樹

請實現一個函式,用來判斷一棵二叉樹是不是對稱的。如果一棵二叉樹和它的映象一樣,那麼它是對稱的。

class Solution {
    public boolean isSymmetric(TreeNode root) {
        if(root == null) return true;
        return isMirror(root,root);
    }
    public boolean isMirror(TreeNode root1,TreeNode root2){
        if(root1 == null && root2 == null) return true;
        if(root1 == null || root2 == null) return false;
        return (root1.val == root2.val) && isMirror(root1.left,root2.right) && isMirror(root1.right,root2.left);
    }
}

劍指 Offer 32 - II. 從上到下列印二叉樹 II

從上到下按層列印二叉樹,同一層的節點按從左到右的順序列印,每一層列印到一行。
同上

劍指 Offer 54. 二叉搜尋樹的第k大節點

給定一棵二叉搜尋樹,請找出其中第k大的節點。

class Solution {
    List<Integer> list = new ArrayList<Integer>();
    public int kthLargest(TreeNode root, int k) {
        inOrder(root);
        return list.get(list.size() - k);
    }
    public void inOrder(TreeNode root){
        if(root == null) return;
        inOrder(root.left);
        list.add(root.val);
        inOrder(root.right);

    }
}

劍指 Offer 55 - I. 二叉樹的深度

同上

劍指 Offer 55 - II. 平衡二叉樹

同上

劍指 Offer 68 - I. 二叉搜尋樹的最近公共祖先

同上

劍指 Offer 68 - II. 二叉樹的最近公共祖先

給定一個二叉樹, 找到該樹中兩個指定節點的最近公共祖先。

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root == null || root == p || root == q) return root;
        TreeNode left = lowestCommonAncestor(root.left, p, q);
        TreeNode right = lowestCommonAncestor(root.right, p, q);
        if(left == null) return right;
        if(right == null) return left;
        return root;
    }
}

面試題 04.02. 最小高度樹

就是構造二叉搜尋樹 同上

面試題 04.04. 檢查平衡性

同上

面試題 17.12. BiNode

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode convertBiNode(TreeNode root) {
        TreeNode head = new TreeNode(0);// 單鏈表的頭指標哨兵
        // 開始中序遍歷
        inorder(root,head);
        return head.right;
    }

    private TreeNode inorder(TreeNode root,TreeNode prev){
        if (root != null){
            prev = inorder(root.left,prev);
            root.left = null;
            prev.right = root;
            prev = root;
            prev = inorder(root.right,prev);
        }
        return prev;
    }
}