[Leetcode][Tree--2]树相关题目汇总/分析/总结--Part2

  1. Binary Tree Con.
    (6) Structure of Tree

    (7) SubTree/Leaves

    (8) Other BT

  2. BST(补充)

  3. Other Tree


[Binary Tree Con.][Structure of Tree]

#100 Same Tree

Easy

  • Sol1 Recursive
    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;
    }

Time complexity : O(N), where N is a number of nodes in the tree, since one visits each node exactly once.

Space complexity : O(log(N)) in the best case of completely balanced tree and O(N) in the worst case of completely unbalanced tree, to keep a recursion stack.

  • Iterative
    public boolean isSameTree(TreeNode p, TreeNode q) {
        if(p == null && q == null) return true;
        if(!check(p, q)) return false;
        Stack<TreeNode> s1 = new Stack<>();
        Stack<TreeNode> s2 = new Stack<>();
        s1.add(p);
        s2.add(q);
        while(!s1.isEmpty()){
            TreeNode n1 = s1.pop();
            TreeNode n2 = s2.pop();
            if(!check(n1,n2))
                return false;
            if(n1 != null) {
                s1.push(n1.left);
                s2.push(n2.left);
                s1.push(n1.right);
                s2.push(n2.right);
            }
        }
        return true;
    }
    public boolean check(TreeNode p, TreeNode q){
        if(p == null && q == null) return true;
        if(p == null || q == null) return false;
        if(p.val != q.val) return false;
        return true;
    }

Time complexity : O(N), where N is a number of nodes in the tree, since one visits each node exactly once.

Space complexity : O(log(N)) in the best case of completely balanced tree and O(N) in the worst case of completely unbalanced tree, to keep a recursion stack.

#101 Symmetric Tree
  • Sol1 Recursive
    public boolean isSymmetric(TreeNode root) {
        return help(root, root);
    }
    public boolean help(TreeNode t1, TreeNode t2){
        if(t1 == null && t2 == null) return true;
        if(t1 == null || t2 == null) return false;
        if(t1.val == t2.val) return help(t1.left, t2.right) && help(t1.right, t2.left);
        return false;
    }

Time O(n)
Space O(n)

  • Sol2 Iterative
    public boolean isSymmetric(TreeNode root) {
        Queue<TreeNode> q = new LinkedList<>();
        q.add(root);
        q.add(root);
        while(!q.isEmpty()){
            TreeNode t1 = q.poll();
            TreeNode t2 = q.poll();
            if(t1 == null && t2 == null) continue;
            if(t1 == null || t2 == null) return false;
            if(t1.val != t2.val) return false;
            q.add(t1.left);
            q.add(t2.right);
            q.add(t1.right);
            q.add(t2.left);
        }
        return true;
    }

Time O(n)
Space O(n)

#965 Univalued Binary Tree
  • Sol1 Recursive
    public boolean isUnivalTree(TreeNode root) {
        if(root == null) return true;
        if(root.left != null || root.right != null){
            if(root.left == null) return root.val == root.right.val && isUnivalTree(root.right);
            if(root.right == null) return root.val == root.left.val &&isUnivalTree(root.left);
            return root.val == root.right.val && root.val == root.left.val && isUnivalTree(root.left) && isUnivalTree(root.right);
        }
        return true;
    }

Time: O(n)
Space: O(H) height

#958 Check Completeness of a Binary Tree
  • Sol BFS
public boolean isCompleteTree(TreeNode root) {
        if(root == null) return true;
        Queue<TreeNode> q = new LinkedList<>();
        q.add(root);
        int level = 0;
        while(!q.isEmpty()){
            int size = q.size();
            boolean check = true;
            for(int i = 0; i < size; i++){
                TreeNode cur = q.poll();
                if(cur.left != null && size != 1 << level) return false;
                if(cur.left != null) {
                    if(!check) return false;
                    q.add(cur.left);
                }else check = false;
                if(cur.right != null) {
                    if(!check) return false;
                    q.add(cur.right);
                }else check = false;
            }
            level++;
        }
        return true;
    }

Time O(N)
Space O(N)

#951 Flip Equivalent Binary Trees
  • Sol Recursive
    public boolean flipEquiv(TreeNode root1, TreeNode root2) {
        if(root1 == null && root2 == null) return true;
        if(root1 == null || root2 == null) return false;
        if(root1.val == root2.val){
            boolean check1 = flipEquiv(root1.left, root2.left) && flipEquiv(root1.right, root2.right);
            boolean check2 = flipEquiv(root1.left, root2.right) && flipEquiv(root1.right, root2.left);
            boolean c = check1 || check2;
            return c;
        }else return false;
    }

Time O(min(n1, n2))
Space O(min(h1, h2))


[Binary Tree Con.][SubTree/Leaves]

#222 Count Complete Tree Nodes
  • BFS
    public int countNodes(TreeNode root) {
        if(root == null) return 0;
        Queue<TreeNode> q = new LinkedList<>();
        q.add(root);
        int res = 0;
        while(!q.isEmpty()){
            int size = q.size();
            res += size;
            for(int i = 0; i < size; i++){
                TreeNode cur = q.poll();
                if(cur.left != null) q.add(cur.left);
                if(cur.right != null) q.add(cur.right);
            }
        }
        return res;
    }

Time O(n)
Space O(n)

  • Sol1 Recursive
    public int countNodes(TreeNode root) {
        if(root == null) return 0;
        int left_height = help(root.left);
        int right_height = help(root.right);
        if(left_height == right_height){
            return left_height == 0? 1 : (1 << left_height) - 1 + 1 + countNodes(root.right); 
        }else{
            return right_height == 0? countNodes(root.left) + 1:(1 << right_height) - 1 + 1 + countNodes(root.left); 
        }
    }
    public int help(TreeNode root){
        int height = 0;
        while(root != null){
            height++;
            root = root.left;
        }
        return height;
    }

Time O(log(n))
Space O(log(n))

#508 Most Frequent Subtree Sum
  • Sol1 HashMap
int max_count = 0;
    Map<Integer, Integer> sum_hash;
    Map<Integer, ArrayList<Integer>> count_hash;
    public int[] findFrequentTreeSum(TreeNode root) {
        sum_hash = new HashMap<>(); //<sum, count>
        help(root);
        ArrayList<Integer> re = new ArrayList<>();
        if(max_count == 0) return new int[0];
        for (Map.Entry<Integer, Integer> entry : sum_hash.entrySet()) {
            if(max_count == entry.getValue()){
                re.add(entry.getKey());
            }
        }
        int[] res = new int[re.size()];
        int i = 0;
        for(Integer a: re){
            res[i++] = a;
        }
        return res;
    }
    public int help(TreeNode root){
        if(root == null) return 0;
        int sum = help(root.left) + help(root.right) + root.val;
        if(sum_hash.containsKey(sum)){
            sum_hash.put(sum, sum_hash.get(sum)+1);
        }else{
            sum_hash.put(sum, 1);
        }
        if(sum_hash.get(sum) > max_count) max_count = sum_hash.get(sum);
        return sum;
    }
#993 Cousins in Binary Tree
  • Sol1 DFS
    TreeNode parent = null;
    public boolean isCousins(TreeNode root, int x, int y) {
        int find_x = find(root, x, 1, parent);
        TreeNode parent_x = null;
        if(parent != null) parent_x = parent;
        
        parent = null;
        int find_y = find(root, y, 1, parent);
        TreeNode parent_y = null;
        if(parent != null) parent_y = parent;
        return find_x == find_y && parent_x != parent_y;
    }
    public int find(TreeNode root, int cur, int level, TreeNode parent){
        if(root == null) return 0;
        if(root.val == cur){
            this.parent = parent;
            return level;
        }
        int ld = find(root.left, cur, level+1, root);
        if(ld != 0) return ld;
        return find(root.right, cur, level + 1, root);
    }

Time O(n)
Space O(h)


[Binary Tree Con.][Other BT]

#116 Populating Next Right Pointers in Each Node
  • Sol1 Pre order
    Recursive
    public Node connect(Node root) {
        if(root == null || root.left == null) return root;
        root.left.next = root.right;
        if(root.next!=null)
            root.right.next = root.next.left;
        connect(root.left);
        connect(root.right);
        return root;
    }

Time O(n)
Space O(1)

  • Sol2 Level Order
    public Node connect(Node root) {
        if(root==null) return root;
        Queue<Node> q = new LinkedList<>();
        q.offer(root);
        while(!q.isEmpty()){
            int size = q.size();
            Node previous = null;
            for(int i = 0; i < size; i++){
                Node cur = q.poll();
                if(previous != null) previous.next = cur;
                previous = cur;
                if(cur.left!=null) q.offer(cur.left);
                if(cur.right!=null) q.offer(cur.right);
            }
        }
        return root;
    }

Time O(n)
Space O(n)

#117 Populating Next Right Pointers in Each Node II
  • Sol1 Level Order
    public Node connect(Node root) {
        if(root==null) return root;
        Queue<Node> q = new LinkedList<>();
        q.offer(root);
        while(!q.isEmpty()){
            int size = q.size();
            Node previous = null;
            for(int i = 0; i < size; i++){
                Node cur = q.poll();
                if(previous != null) previous.next = cur;
                previous = cur;
                if(cur.left!=null) q.offer(cur.left);
                if(cur.right!=null) q.offer(cur.right);
            }
        }
        return root;
    }

Time O(n)
Space O(n)

  • Sol2 Dummy node
    public Node connect(Node root) {
        Node dummy = new Node();
        Node pre = dummy;
        Node cur = root;
        while(cur != null){
            if(cur.left != null){
                pre.next = cur.left;
                pre = pre.next;
            }
            if(cur.right != null){
                pre.next = cur.right;
                pre = pre.next;
            }
            cur = cur.next;
            if(cur == null){
                pre = dummy;
                cur = pre.next;
                dummy.next = null; //keep dummy is new Node();
            }
        }
        return root;
}

Time O(n)
Space O(1)

#236 Lowest Common Ancestor of a Binary Tree
  • Sol1 Recursive
    DFS搜索p与q,记录每个node点的left,right,mid。mid为node是否为p,q其中一个。left为p或q是否存在左分支上,right同理。
    TreeNode res;
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        res = null;
        help(root, p, q);
        return res;
    }
    public boolean help(TreeNode root, TreeNode p, TreeNode q){
        if(root == null) return false;
        int left = help(root.left, p, q) ? 1 : 0;
        int right = help(root.right, p, q) ? 1 : 0;
        int mid = (root.val == p.val || root.val == q.val) ? 1 : 0;
        if(left + right + mid >=2){
            res = root;
        }
        return left + right + mid > 0;
    }

Time O(n)
Space O(n)

  • Sol2 Iterative
    map存储node的parent,之后backtrack查找共同的ancestor
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root == null) return null;
        Map<TreeNode,TreeNode> map = new HashMap<>(); //node, parent
        Stack<TreeNode> s = new Stack<>();
        s.push(root);
        map.put(root, null);
        while(!map.containsKey(p) || !map.containsKey(q)){
            TreeNode cur = s.pop();
            if(cur.left != null){
                map.put(cur.left, cur);
                s.push(cur.left);
            }
            if(cur.right != null){
                map.put(cur.right, cur);
                s.push(cur.right);
            }
        }
        
        Set<TreeNode> back = new HashSet<>();
        while(p != null){
            back.add(p);
            p = map.get(p);
        }
        while(!back.contains(q)){
            q = map.get(q);
        }
        return q;
    }

Time O(n)
Space O(n)

#297 Serialize and Deserialize Binary Tree

可以与449. Serialize and Deserialize BST比较做

  • Sol1 Recursive
// Encodes a tree to a single string.
    public String serialize(TreeNode root) {
        StringBuilder sb = new StringBuilder();
        ser_help(sb, root);
        return sb.toString();
    }
    public void ser_help(StringBuilder sb, TreeNode root){
        if(root == null){
            sb.append("*").append(",");
            return;
        }
        sb.append(root.val).append(",");
        ser_help(sb, root.left);
        ser_help(sb, root.right);
    }

    // Decodes your encoded data to tree.
    public TreeNode deserialize(String data) {
        Queue<String> q = new LinkedList<>();
        q.addAll(Arrays.asList(data.split(",")));
        return des_help(q);
    }
    public TreeNode des_help(Queue<String> q){
        String cur = q.poll();
        if(cur.equals("*")) return null;
        TreeNode root = new TreeNode(Integer.valueOf(cur));
        root.left = des_help(q);
        root.right = des_help(q);
        return root;
        
    }

[BST(补充)]

#235 Lowest Common Ancestor of a Binary Search Tree
  • Sol1 Recursive
    三种情况递归:同在左/同在右/左右各一个
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        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;
    }

Time O(n)
Space O(n)

  • Sol2 Iterative
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        int p_val = p.val, q_val = q.val;
        TreeNode cur = root;
        while(cur != null){
            if(cur.val < p_val && cur.val < q_val) cur = cur.right;
            else if(cur.val > p_val && cur.val > q_val) cur = cur.left;
            else return cur;
        }
        return null;
    }

Time O(n)
Space O(1) 不需要stack因为不需要backtrack


[Others]

#337 House Robber III
  • Sol1 DFS
    public int rob(TreeNode root) {
        if(root == null) return 0;
        int[] res = new int[2];
        res = help(root);
        return Math.max(res[0], res[1]);
    }
    public int[] help(TreeNode root){
        int[] res = new int[2];
        if(root == null){
            res[0] = 0;
            res[1] = 0;
            return res;
        }
        int[] left = help(root.left);
        int[] right = help(root.right);
        res[0] = root.val + left[1] + right[1];
        res[1] = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);
        return res;
    }
#834 Sum of Distances in Tree

Hard

  • Sol Subtree + DFS
    List<Set>存树结构,pre_order遍历更新count与res,得到root的正确res与每个点的count值,post_order更新所有所有点的res
    List<Set<Integer>> tree;
    int N;
    int[] res, count;
    public int[] sumOfDistancesInTree(int N, int[][] edges) {
        tree = new ArrayList<>();
        this.N = N;
        res = new int[N];
        count = new int[N];
        Arrays.fill(count, 1);
        for(int i = 0; i < N; i++){
            tree.add(new HashSet<>());
        }
        for(int[] edge: edges){
            tree.get(edge[0]).add(edge[1]);
            tree.get(edge[1]).add(edge[0]);
        }
        dfs(0, -1);
        dfs2(0, -1);
        return res;
    }
    public void dfs(int node, int parent){
        for(int child: tree.get(node)){
            if(child != parent){
                dfs(child, node);
                count[node] += count[child];
                res[node] += res[child] + count[child];
            }
        }
    }
    public void dfs2(int node, int parent){
        for(int child: tree.get(node)){
            if(child != parent){
                res[child] = res[node] - count[child] + N - count[child];
                dfs2(child, node);
            }
        }
    }
#310 Minimum Height Trees
  • Sol BFS
    List<Set>存树结构,记录每个点的in degree
public List<Integer> findMinHeightTrees(int n, int[][] edges) {
        List<Set<Integer>> tree = new ArrayList<>();
        List<Integer> res = new ArrayList<>();
        if (edges.length == 0) {
            res.add(0);
            return res;
        }
        int[] indegree = new int[n];
        Queue<Integer> q = new LinkedList<>();
        for(int i = 0; i < n; i++)
        {
            tree.add(new HashSet<>());
        }   
        for(int[] edge: edges){
            tree.get(edge[0]).add(edge[1]);
            tree.get(edge[1]).add(edge[0]);
        }
        for(int i = 0; i < n; i++){
            indegree[i] = tree.get(i).size();
            if(indegree[i] == 1) q.add(i);
        }
        int count = 0;
        while(!q.isEmpty()){
            int size = q.size();
            count += size;
            for(int i = 0; i < size; i++){
                int cur = q.poll();
                indegree[cur]--;
                if(count == n) {
                    res.add(cur);
                }
                for(Integer node: tree.get(cur)){
                    if(indegree[node]!=0){
                        indegree[node]--;
                        if(indegree[node] == 1) q.add(node);
                    }
                }
            }
        }
        return res;
    }
** 558* Quad Tree Intersection
  • Sol Recursive
    public Node intersect(Node quadTree1, Node quadTree2) {
        if(quadTree1.isLeaf){
            return quadTree1.val ? quadTree1 : quadTree2;
        }else if(quadTree2.isLeaf){
            return quadTree2.val ? quadTree2 : quadTree1;
        }
        Node TL = intersect(quadTree1.topLeft, quadTree2.topLeft);
        Node TR = intersect(quadTree1.topRight, quadTree2.topRight);
        Node BL = intersect(quadTree1.bottomLeft, quadTree2.bottomLeft);
        Node BR = intersect(quadTree1.bottomRight, quadTree2.bottomRight);
        if(TL.isLeaf && TR.isLeaf && BL.isLeaf && BR.isLeaf && TL.val == TR.val && TL.val == BL.val && TL.val == BR.val) 
            return new Node(TL.val, true, null, null, null, null);
        Node res = new Node(false, false, TL, TR, BL, BR);
        return res;
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容