LeetCode刷题:树1

四种基本遍历

围绕着三种遍历dfs有许多的习题
其中一大类是后序遍历的状态转移,自底向上的写法,有返回值的dfs,通过左右孩子推出中间节点的值或者状态然后继续上推

前序:

 public void preTraversal(Node node){
    
    
       if (node == null) //很重要,必须加上 当遇到叶子节点用来停止向下遍历
             return;
         System.out.print(node.getValue()+" ");
        preTraversal(node.getLeft());
        preTraversal(node.getRight());
 }

中序:

public void MidTraversal(Node node){
    
    
      if (node == null)
          return;
     MidTraversa(node.getLeft());
     System.out.print(node.getValue()+" ");
     MidTraversa(node.getRight());
 }

后序:

 public void postTraversal(Node node){
    
    
         if (node == null)
                 return;
        postTraversal(node.getLeft());
        postTraversal(node.getRight());
        System.out.print(node.getValue()+" ");
 }

三种顺序的stack写法

前序:

class Solution {
    
    
public:
    vector<int> preorderTraversal(TreeNode* root) {
    
    
        vector<int> result;
        stack<TreeNode*> st;
        if (root != NULL) st.push(root);
        while (!st.empty()) {
    
    
            TreeNode* node = st.top();
            if (node != NULL) {
    
    
                st.pop();
                if (node->right) st.push(node->right);  // 右
                if (node->left) st.push(node->left);    // 左
                // 中,push NULL是一个标志位,当前中中间节点
                st.push(node);                          
                st.push(NULL);
            } else {
    
    
                st.pop();
                node = st.top();
                st.pop();
                result.push_back(node->val);
            }
        }
        return result;
    }
};

后序:

class Solution {
    
    
public:
    vector<int> postorderTraversal(TreeNode* root) {
    
    
        vector<int> result;
        stack<TreeNode*> st;
        if (root != NULL) st.push(root);
        while (!st.empty()) {
    
    
            TreeNode* node = st.top();
            if (node != NULL) {
    
    
                st.pop();
                st.push(node);                          // 中
                st.push(NULL);

                if (node->right) st.push(node->right);  // 右
                if (node->left) st.push(node->left);    // 左

            } else {
    
    
                st.pop();
                node = st.top();
                st.pop();
                result.push_back(node->val);
            }
        }
        return result;
    }
};

中序:

class Solution {
    
    
public:
    vector<int> inorderTraversal(TreeNode* root) {
    
    
        vector<int> result;
        stack<TreeNode*> st;
        if (root != NULL) st.push(root);
        while (!st.empty()) {
    
    
            TreeNode* node = st.top();
            if (node != NULL) {
    
    
                st.pop(); // 将该节点弹出,避免重复操作,下面再将右中左节点添加到栈中
                if (node->right) st.push(node->right);  // 添加右节点(空节点不入栈)

                st.push(node);                          // 添加中节点
                st.push(NULL); // 中节点访问过,但是还没有处理,加入空节点做为标记。

                if (node->left) st.push(node->left);    // 添加左节点(空节点不入栈)
            } else {
    
     // 只有遇到空节点的时候,才将下一个节点放进结果集
                st.pop();           // 将空节点弹出
                node = st.top();    // 重新取出栈中元素
                st.pop();
                result.push_back(node->val); // 加入到结果集
            }
        }
        return result;
    }
};

层序遍历:

public List<List<Integer>> levelOrder(TreeNode root) {
    
    
        List<List<Integer>> res = new LinkedList<>();
        BFS(root, res);
        return res;
    }
 
    private void BFS(TreeNode treeNode, List<List<Integer>> res) {
    
    
        if (treeNode == null) {
    
    
            return;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(treeNode);
        while (!queue.isEmpty()) {
    
    
            List<Integer> level = new LinkedList<>();
            int n = queue.size();
            for(int i = 0; i < n; i++) {
    
    
                TreeNode tmp = queue.poll();
                if(tmp != null) {
    
    
                    level.add(tmp.val);
                    queue.offer(tmp.left);
                    queue.offer(tmp.right);
                }
            }
            if(level.size() > 0) {
    
    
                res.add(level);
            }
        }
    }

后续遍历 + 状态转移 + 结果存储类

自底向上的解法,配合状态转移与最终结果记录,一般采用后续遍历

https://leetcode-cn.com/problems/balanced-binary-tree/
在这里插入图片描述

核心思路:
自底向上,有状态的转移;
后序遍历,左孩子错右孩子错那么parent一定是错的。
返回值与存储结构

class Solution {
    
    
    public boolean isBalanced(TreeNode root) {
    
    
        return height(root) >= 0;
    }
 
    public int height(TreeNode root) {
    
    
        if (root == null) {
    
    
            return 0;
        }
        int leftHeight = height(root.left);
        int rightHeight = height(root.right);
        if (leftHeight == -1 || rightHeight == -1 || Math.abs(leftHeight - rightHeight) > 1) {
    
    
            return -1; // -1 作为失败标志
        } else {
    
    
            return Math.max(leftHeight, rightHeight) + 1;  // 正常的高度返回
        }
    }
}

同类题1
https://leetcode-cn.com/problems/diameter-of-binary-tree/ 在这里插入图片描述后序遍历的又一个例子,变来变去的只是从子问题到大问题的推导

class Solution {
    
    
    Integer ans = 0;
    public int diameterOfBinaryTree(TreeNode root) {
    
    
        if(root == null) {
    
    
            return 0;
        }
        postOrder(root);
        return ans - 1;
    }
 
    private int postOrder(TreeNode root) {
    
    
        if(root == null) {
    
    
            return 0;
        }
        int left = postOrder(root.left);
        int right = postOrder(root.right);
        ans = Math.max(ans,left + right + 1); // 最终结果:使用一个公共字段保存结果
        return Math.max(left, right) + 1; // 当前状态:大问题的解存储的状态转移不同,存储的实际上是高度
    }
}

同类题2 在这里插入图片描述

class Solution {
    
    
    Integer ans =  Integer.MIN_VALUE;
    public int maxPathSum(TreeNode root) {
    
    
        if(root == null) {
    
    
            return 0;
        }
        postOrder(root);
        return ans;
    }
 
    private int postOrder(TreeNode root) {
    
    
        if(root == null) {
    
    
            return 0;
        }
        int left = Math.max(postOrder(root.left), 0);
        int right = Math.max(postOrder(root.right), 0);
        ans = Math.max(ans, left + right + root.val); // 使用一个公共字段保存结果
        return Math.max(left, right) + root.val; // 大问题的解存储的状态转移不同
    }
}

翻转二叉树:
在这里插入图片描述

简单的后续遍历:

public TreeNode invertTree(TreeNode root) {
    
    
        if(root == null) {
    
    
            return root;
        }
        return postOrder(root);
    }
 
    private TreeNode postOrder(TreeNode root) {
    
    
        if(root == null) {
    
    
            return root;
        }
        postOrder(root.left);
        postOrder(root.right);
        TreeNode tmp = root.left;
        root.left = root.right;
        root.right = tmp;
        return root;
    }

求最大BST树 在这里插入图片描述二叉搜索树特征:中序遍历val递增
还是后序遍历

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    
    
 
    class Result {
    
    
        TreeNode node; // BST根节点
        int size; // BST的size
        int max; // BST的最大值
        int min; // BST的最小值
    }
 
    public int largestBSTSubtree(TreeNode root) {
    
    
        Result r = visit(root);
        return r == null ? 0 : r.size;
    }
 
    public Result visit(TreeNode node) {
    
    
        if (node == null) return null;
 
        Result l = null, r = null;
        if (node.left != null) l = visit(node.left);
        if (node.right != null) r = visit(node.right);
 
        // 当前树为BST
        boolean lValid = (l == null || (l.node == node.left && l.max < node.val));
        boolean rValid = (r == null || (r.node == node.right && r.min > node.val));
        if (lValid && rValid) {
    
    
            Result result = new Result();
            result.node = node;
            result.max = r == null ? node.val : r.max;
            result.min = l == null ? node.val : l.min;
            result.size = (l == null ? 0 : l.size) + (r == null ? 0 : r.size) + 1;
            return result;
        }
 
        // 左右子树中找到了BST
        if (l != null && r != null) {
    
    
            return l.size > r.size ? l : r;
        }
        if (l != null) return l;
        if (r != null) return r;
 
        return null;
    }
}
 
作者:jzj1993
链接:https://leetcode-cn.com/problems/largest-bst-subtree/solution/si-lu-qing-xi-de-javadai-ma-onfu-za-du-1ms-by-jzj1/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

最近公共祖先
https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/solution/er-cha-shu-de-zui-jin-gong-gong-zu-xian-by-leetc-2/在这里插入图片描述还是后序遍历,父节点的状态转移方程(返回值)如上
最后结果可以通过放置在外面代入求得

class Solution {
    
    
 
    private TreeNode ans;
 
    public Solution() {
    
    
        this.ans = null;
    }
 
    private boolean dfs(TreeNode root, TreeNode p, TreeNode q) {
    
    
        if (root == null) return false;
        boolean lson = dfs(root.left, p, q);
        boolean rson = dfs(root.right, p, q);
      // 结果存储
        if ((lson && rson) || ((root.val == p.val || root.val == q.val) && (lson || rson))) {
    
    
            ans = root;
        } 
      // 状态转移
        return lson || rson || (root.val == p.val || root.val == q.val);
    }
 
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
    
    
        this.dfs(root, p, q);
        return this.ans;
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_38370441/article/details/115179797