算法題存檔20200627(樹)

給你一棵以 root 爲根的二叉樹和一個 head 爲第一個節點的鏈表。

如果在二叉樹中,存在一條一直向下的路徑,且每個點的數值恰好一一對應以 head 爲首的鏈表中每個節點的值,那麼請你返回 True ,否則返回 False 。

一直向下的路徑的意思是:從樹中某個節點開始,一直連續向下的路徑。

class Solution {
    public boolean isSubPath(ListNode head, TreeNode root) {
        if(head == null) {
            return true;
        }
        if(root == null) {
            return false;
        }
        if(isNext(head, root)) {
            return true;
        }
        return isSubPath(head, root.left) || isSubPath(head, root.right);
    }

    public boolean isNext(ListNode head, TreeNode root) {
        if(head == null) {
            return true;
        }
        if(root == null) {
            return false;
        }
        if(head.val == root.val) {
            return isNext(head.next, root.left) || isNext(head.next, root.right);
        }
        return false;
    }
}

給你一個二叉樹,請你返回其按 層序遍歷 得到的節點值。 (即逐層地,從左到右訪問所有節點)。

 

示例:
二叉樹:[3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7

返回其層次遍歷結果:

[
  [3],
  [9,20],
  [15,7]
]

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> result = new ArrayList<>();
        if(root == null) {
            return result;
        }
        List<TreeNode> queue = new ArrayList<>();
        int num = 1;
        queue.add(root);
        while(!queue.isEmpty()) {
            List<Integer> res = new ArrayList<>();
            int temp = num;
            num = 0;
            for(int i = 0; i < temp; i++) {
                TreeNode t = queue.get(0);
                res.add(t.val);
                if(t.left != null) {
                    queue.add(t.left);
                    num++;
                }
                if(t.right != null) {
                    queue.add(t.right);
                    num++;
                }
                queue.remove(0);
            }
            result.add(res);
        }
        return result;
    }
}

實現一個二叉搜索樹迭代器。你將使用二叉搜索樹的根節點初始化迭代器。

調用 next() 將返回二叉搜索樹中的下一個最小的數。

 

示例:

BSTIterator iterator = new BSTIterator(root);
iterator.next();    // 返回 3
iterator.next();    // 返回 7
iterator.hasNext(); // 返回 true
iterator.next();    // 返回 9
iterator.hasNext(); // 返回 true
iterator.next();    // 返回 15
iterator.hasNext(); // 返回 true
iterator.next();    // 返回 20
iterator.hasNext(); // 返回 false
class BSTIterator {

    LinkedList<Integer> list = new LinkedList<>();

    public BSTIterator(TreeNode root) {
        mid(root);
    }

    /** @return the next smallest number */
    public int next() {
        return list.removeFirst();
    }

    /** @return whether we have a next smallest number */
    public boolean hasNext() {
        return !list.isEmpty();
    }

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

實現一個函數,檢查二叉樹是否平衡。在這個問題中,平衡樹的定義如下:任意一個節點,其兩棵子樹的高度差不超過 1。

示例 1:

給定二叉樹 [3,9,20,null,null,15,7]
    3
   / \
  9  20
    /  \
   15   7
返回 true 。

示例 2:

給定二叉樹 [1,2,2,3,3,null,null,4,4]
      1
     / \
    2   2
   / \
  3   3
 / \
4   4
返回 false 。

class Solution {
    public boolean isBalanced(TreeNode root) {
        return root == null || Math.abs(depth(root.left) - depth(root.right)) <= 1 && isBalanced(root.left) && isBalanced(root.right);
    }


    public Integer depth(TreeNode parent) {
        return parent == null ? 0 : Math.max(depth(parent.left), depth(parent.right)) + 1 ;
    }
}

給定一個二叉樹,它的每個結點都存放着一個整數值。

找出路徑和等於給定數值的路徑總數。

路徑不需要從根節點開始,也不需要在葉子節點結束,但是路徑方向必須是向下的(只能從父節點到子節點)。

二叉樹不超過1000個節點,且節點數值範圍是 [-1000000,1000000] 的整數。

示例:

root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8

      10
     /  \
    5   -3
   / \    \
  3   2   11
 / \   \
3  -2   1

返回 3。和等於 8 的路徑有:

1.  5 -> 3
2.  5 -> 2 -> 1
3.  -3 -> 11

class Solution {
   int result = 0;

    public int pathSum(TreeNode root, int sum) {
        if(root == null) {
            return 0;
        }
        dfs(root, sum);
        pathSum(root.left, sum);
        pathSum(root.right, sum);
        return result;
    }

    public void dfs(TreeNode root, int sum) {
        if(root == null) {
            return;
        }
        int s = sum - root.val;
        if(s == 0) {
           result++;
        }
        dfs(root.left, s);
        dfs(root.right, s);
    }
}

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

 

例如,二叉樹 [1,2,2,3,4,4,3] 是對稱的。

    1
   / \
  2   2
 / \ / \
3  4 4  3

 

但是下面這個 [1,2,2,null,3,null,3] 則不是鏡像對稱的:

    1
   / \
  2   2
   \   \
   3    3

class Solution {
     public boolean isSymmetric(TreeNode root) {
        if(root == null) {
            return true;
        }
        return isMirror(root.left, root.right);
    }

    public boolean isMirror(TreeNode left, TreeNode right) {
        if(left == null && right == null) {
            return true;
        }
        if(left ==null || right == null || left.val != right.val) {
            return false;
        }
        return isMirror(left.left, right.right) && isMirror(left.right, right.left);
    }
}

我們可以爲二叉樹 T 定義一個翻轉操作,如下所示:選擇任意節點,然後交換它的左子樹和右子樹。

只要經過一定次數的翻轉操作後,能使 X 等於 Y,我們就稱二叉樹 X 翻轉等價於二叉樹 Y。

編寫一個判斷兩個二叉樹是否是翻轉等價的函數。這些樹由根節點 root1 和 root2 給出。

 

示例:

輸入:root1 = [1,2,3,4,5,6,null,null,null,7,8], root2 = [1,3,2,null,6,4,5,null,null,null,null,8,7]
輸出:true
解釋:我們翻轉值爲 1,3 以及 5 的三個節點。
Flipped Trees Diagram

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

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

例如,給定一個 3叉樹 :

 

 

返回其後序遍歷: [5,6,3,2,4,1].

class Solution {
     List<Integer> result = new ArrayList<>();

    public List<Integer> postorder(Node root) {
        if(root == null) {
            return result;
        }
        if(root.children != null) {
            root.children.forEach(this::postorder);
        }
        result.add(root.val);
        return result;
    }
}

滿二叉樹是一類二叉樹,其中每個結點恰好有 0 或 2 個子結點。

返回包含 N 個結點的所有可能滿二叉樹的列表。 答案的每個元素都是一個可能樹的根結點。

答案中每個樹的每個結點都必須有 node.val=0。

你可以按任何順序返回樹的最終列表。

class Solution {
    public List<TreeNode> allPossibleFBT(int N) {
        List<TreeNode> result = new ArrayList<>();
        if (N % 2 == 0) {
            return result;
        }
        if(N == 1) {
            TreeNode head = new TreeNode(0);
            result.add(head);
            return result;
        }
        for(int i = 1; i < N; i += 2) {
            List<TreeNode> left = allPossibleFBT(i);
            List<TreeNode> right = allPossibleFBT(N - 1 - i);

            for(int j = 0; j < left.size(); j++) {
                for(int m = 0; m < right.size(); m++) {
                    TreeNode head = new TreeNode(0);
                    head.left = left.get(j);
                    head.right = right.get(m);
                    result.add(head);
                }
            }
        }

        return result;
    }
}

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

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

例如,給定如下二叉搜索樹:  root = [6,2,8,0,4,7,9,null,null,3,5]

 

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root == 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;
    }
}

給定一棵二叉樹,返回所有重複的子樹。對於同一類的重複子樹,你只需要返回其中任意一棵的根結點即可。

兩棵樹重複是指它們具有相同的結構以及相同的結點值。

class Solution {
    public List<TreeNode> result = new ArrayList<>();
    public HashMap<String, Integer> map = new HashMap<>();

    public List<TreeNode> findDuplicateSubtrees(TreeNode root) {
        pre(root);
        return result;
    }

    public String pre(TreeNode root) {
        if(root == null) {
            return "#";
        }
        String s = root.val + "," + pre(root.left) + "," + pre(root.right);
        if(map.get(s) != null && map.get(s) == 1) {
            result.add(root);
        }
        Integer i = map.get(s);
        if(i == null) {
            map.put(s, 1);
        } else {
            map.put(s, ++i);
        }
        return s;
    }
}

給你一棵二叉樹,請你返回滿足以下條件的所有節點的值之和:

    該節點的祖父節點的值爲偶數。(一個節點的祖父節點是指該節點的父節點的父節點。)

如果不存在祖父節點值爲偶數的節點,那麼返回 0 。

class Solution {
    public int sumEvenGrandparent(TreeNode root) {
        int result = dfs(null, null, root);
        return result;
    }

    public int dfs(TreeNode gf, TreeNode f, TreeNode root) {
        int result = 0;
        if(root == null) {
            return result;
        }
        if(gf != null && f != null && gf.val % 2 == 0) {
            result += root.val;
        }
        result += dfs(f, root, root.left);
        result += dfs(f, root, root.right);
        return result;
    }
}

 

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