剑指offer——树篇

面试题07. 重建二叉树

//C/** * Definition for a binary tree node. * struct TreeNode { *     int val; *     struct TreeNode *left; *     struct TreeNode *right; * }; */struct TreeNode* buildTree(int* preorder, int preorderSize, int* inorder, int inorderSize){    if(preorderSize == 0){        return NULL;    }    int rootNum  = preorder[0];      struct TreeNode *root;    int i ;    root = (struct TreeNode *)malloc(sizeof(struct TreeNode));    root->val = rootNum;    for(i = 0; i < inorderSize; i++){        if(inorder[i] == rootNum){            break;        }    }    root->left = (i == 0) ? NULL : buildTree(preorder+1, i, inorder, i);    root->right = (i == inorderSize-1) ? NULL : buildTree(preorder+1+i, preorderSize-1-i, inorder+1+i, inorderSize-1-i);             return root;}```# 面试题32-I.从上到下打印二叉树![在这里插入图片描述](https://img-blog.csdnimg.cn/20200331143332949.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjA3MjI4MA==,size_16,color_FFFFFF,t_70)```java//java anan 2020.3.31class Solution {    public int[] levelOrder(TreeNode root) {        if(root == null)   return new int[0];  //输入:[]        Queue<TreeNode> queue = new LinkedList<>();        ArrayList<Integer> res = new ArrayList<>();        queue.offer(root);        while(!queue.isEmpty()){            TreeNode p = queue.poll();            res.add(p.val);            if(p.left != null)   queue.offer(p.left);            if(p.right != null)  queue.offer(p.right);        }         return res.stream().mapToInt(Integer::intValue).toArray();              }}```# 面试题32-II.从上到下打印二叉树 (102)![在这里插入图片描述](https://img-blog.csdnimg.cn/20200331161007559.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjA3MjI4MA==,size_16,color_FFFFFF,t_70)## 安安:迭代[参考题解](https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-ii-lcof/solution/mian-shi-ti-32-ii-cong-shang-dao-xia-da-yin-er-c-5/)```java//javaclass Solution {    public List<List<Integer>> levelOrder(TreeNode root) {        Queue<TreeNode> queue = new LinkedList<>();        List<List<Integer>> res = new ArrayList<>();        if(root == null)   return res;  //输入:[]        queue.offer(root);                while(!queue.isEmpty()){            List<Integer> tmp = new ArrayList<Integer>();                     for(int i = queue.size(); i > 0; i--){                TreeNode p = queue.poll();                tmp.add(p.val);                if(p.left != null)   queue.offer(p.left);                if(p.right != null)  queue.offer(p.right);            }            res.a# 

```c
//C

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */


struct TreeNode* buildTree(int* preorder, int preorderSize, int* inorder, int inorderSize){
    if(preorderSize == 0){
        return NULL;
    }

    int rootNum  = preorder[0];  
    struct TreeNode *root;
    int i ;

    root = (struct TreeNode *)malloc(sizeof(struct TreeNode));
    root->val = rootNum;

    for(i = 0; i < inorderSize; i++){
        if(inorder[i] == rootNum){
            break;
        }
    }
    root->left = (i == 0) ? NULL : buildTree(preorder+1, i, inorder, i);
    root->right = (i == inorderSize-1) ? NULL : buildTree(preorder+1+i, preorderSize-1-i, inorder+1+i, inorderSize-1-i);
         
    return root;
}

面试题32-I.从上到下打印二叉树

在这里插入图片描述

//java anan 2020.3.31
class Solution {
    public int[] levelOrder(TreeNode root) {
        if(root == null)   return new int[0];  //输入:[]

        Queue<TreeNode> queue = new LinkedList<>();
        ArrayList<Integer> res = new ArrayList<>();

        queue.offer(root);
        while(!queue.isEmpty()){
            TreeNode p = queue.poll();
            res.add(p.val);
            if(p.left != null)   queue.offer(p.left);
            if(p.right != null)  queue.offer(p.right);
        } 

        return res.stream().mapToInt(Integer::intValue).toArray();   
       
    }
}

面试题32-II.从上到下打印二叉树 (102)

在这里插入图片描述

安安:迭代

参考题解

//java
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        Queue<TreeNode> queue = new LinkedList<>();
        List<List<Integer>> res = new ArrayList<>();

        if(root == null)   return res;  //输入:[]

        queue.offer(root);
        
        while(!queue.isEmpty()){
            List<Integer> tmp = new ArrayList<Integer>();         
            for(int i = queue.size(); i > 0; i--){
                TreeNode p = queue.poll();
                tmp.add(p.val);
                if(p.left != null)   queue.offer(p.left);
                if(p.right != null)  queue.offer(p.right);
            }
            res.add(tmp);        
        }

        return res;
    }
}

官解1:迭代 O(n)

官方解答

//java
class Solution {
  public List<List<Integer>> levelOrder(TreeNode root) {
    List<List<Integer>> levels = new ArrayList<List<Integer>>();
    if (root == null) return levels;

    Queue<TreeNode> queue = new LinkedList<TreeNode>();
    queue.add(root);
    int level = 0;
    while ( !queue.isEmpty() ) {
      // start the current level
      levels.add(new ArrayList<Integer>());

      // number of elements in the current level
      int level_length = queue.size();
      for(int i = 0; i < level_length; ++i) {
        TreeNode node = queue.remove();

        // fulfill the current level
        levels.get(level).add(node.val);

        // add child nodes of the current level
        // in the queue for the next level
        if (node.left != null) queue.add(node.left);
        if (node.right != null) queue.add(node.right);
      }
      // go to next level
      level++;
    }
    return levels;
  }
}

作者:LeetCode
链接:https://leetcode-cn.com/problems/binary-tree-level-order-traversal/solution/er-cha-shu-de-ceng-ci-bian-li-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

官解2:递归 O(n) dfs+层标记

//java class Solution {
    List<List<Integer>> levels = new ArrayList<List<Integer>>();

    public void helper(TreeNode node, int level) {
        // start the current level
        if (levels.size() == level)
            levels.add(new ArrayList<Integer>());

         // fulfil the current level
         levels.get(level).add(node.val);

         // process child nodes for the next level
         if (node.left != null)
            helper(node.left, level + 1);
         if (node.right != null)
            helper(node.right, level + 1);
    }
    
    public List<List<Integer>> levelOrder(TreeNode root) {
        if (root == null) return levels;
        helper(root, 0);
        return levels;
    }
}

作者:LeetCode
链接:https://leetcode-cn.com/problems/binary-tree-level-order-traversal/solution/er-cha-shu-de-ceng-ci-bian-li-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

面试题32-III.从上到下打印二叉树

在这里插入图片描述

法1:迭代

//java
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        Queue<TreeNode> queue = new LinkedList<>();
        List<List<Integer>> res = new ArrayList<>();
        if(root != null) queue.add(root);
        while(!queue.isEmpty()) {
            List<Integer> tmp = new ArrayList<>();
            for(int i = queue.size(); i > 0; i--) {
                TreeNode node = queue.poll();
                tmp.add(node.val);
                if(node.left != null) queue.add(node.left);
                if(node.right != null) queue.add(node.right);
            }
            if(res.size() % 2 == 1) Collections.reverse(tmp);  //反转
            res.add(tmp);
        }
        return res;
    }
}

作者:jyd
链接:https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-iii-lcof/solution/mian-shi-ti-32-iii-cong-shang-dao-xia-da-yin-er--3/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
//java 不用反转

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        Queue<TreeNode> queue = new LinkedList<>();
        List<List<Integer>> res = new ArrayList<>();
        if(root != null) queue.add(root);
        while(!queue.isEmpty()) {
            List<Integer> tmp = new ArrayList<>();
            for(int i = queue.size(); i > 0; i--) {
                TreeNode node = queue.poll();
                if(res.size() % 2 == 1){
                    tmp.add(0, node.val);
                }else{
                    tmp.add(node.val);
                }               
                if(node.left != null) queue.add(node.left);
                if(node.right != null) queue.add(node.right);
            }
           
            res.add(tmp);
        }
        return res;
    }
}

法2:递归

//java
//根节点认为第0层 偶数层从末尾追加  奇数层从头添加
class Solution {

    List<List<Integer>> res = new ArrayList<>();

    public void helper(TreeNode node, int level){
        if(res.size() == level){
            res.add(new ArrayList<Integer>());
        }

        if(level%2 == 0)  res.get(level).add(node.val); //偶数
        else res.get(level).add(0, node.val); //奇数

        if(node.left != null) helper(node.left, level+1);
        if(node.right != null) helper(node.right, level+1);
    }

    public List<List<Integer>> levelOrder(TreeNode root) {
        if(root == null)  return res;
        helper(root, 0);
        return res;
    }
}

法3:双栈法(剑指offer)

在这里插入图片描述
在这里插入图片描述

//Java 安安 2020.3.31
//根节点作为第0行 
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {   
        List<List<Integer>> res = new ArrayList<>();

        Stack<TreeNode> s1 = new Stack<>();  //存储奇数行
        Stack<TreeNode> s2 = new Stack<>();  //存储偶数行

        if(root != null) s2.push(root);

        while(!s1.empty() || !s2.empty()) {
            List<Integer> tmp = new ArrayList<>();
            if(!s2.empty()){
                while(!s2.empty()){
                    TreeNode p = s2.pop();
                    tmp.add(p.val);
                    if(p.left != null) s1.push(p.left);
                    if(p.right != null) s1.push(p.right);
                }
                res.add(tmp);
            }

            if(!s1.empty()){
                tmp = new ArrayList<>();
                while(!s1.empty()){
                    TreeNode p = s1.pop();
                    tmp.add(p.val);
                    if(p.right != null) s2.push(p.right);
                    if(p.left != null)  s2.push(p.left);
                }         
                res.add(tmp);
            }
        }
        return res;
    }
}

面试题26.树的子结构

在这里插入图片描述
在这里插入图片描述

版本1

//java  anan 2020.4.3
class Solution {
    TreeNode A1;

    public boolean isSubStructure(TreeNode A, TreeNode B) {       
        if(A == null || B == null) return false;
        boolean flag1 = inOrderTraverse(A, B);
        boolean flag2 = false;;
        if(flag1){
            flag2 = inOrderTraverseTwoTrees(A1, B);
        } 
        System.out.println(flag1 + " " + flag2);
        return flag1&&flag2;      
    }

    public boolean inOrderTraverse(TreeNode A, TreeNode B){
        if(A != null && B != null){
            if(A.val != B.val){
                return inOrderTraverse(A.left, B) || inOrderTraverse(A.right, B);
            }else{
                A1 = A;
                return true;
            }
        }else{
            return false;
        }
    }

    public boolean inOrderTraverseTwoTrees(TreeNode A, TreeNode B){
        if(B != null &&  A != null){
            if(A.val == B.val){
                if(B.left == null) return inOrderTraverseTwoTrees(A.right, B.right);
                else if(B.right == null)  return inOrderTraverseTwoTrees(A.left, B.left);
                else return inOrderTraverseTwoTrees(A.left, B.left) && inOrderTraverseTwoTrees(A.right, B.right);
            }else{
                return false;
            }
        }else if(B == null){
            return true;
        }   
        return false;     
    }
}

版本2

//java  对上一个版本的代码进行了优化  但还是无法判断第一个值相同的节点,只能判断一个
class Solution {

    public boolean isSubStructure(TreeNode A, TreeNode B) {       
        return hasSameValueNode(A,B);
    }

    public boolean hasSameValueNode(TreeNode A, TreeNode B){ //判断A中有没有和B根节点值相同的节点
        if(A == null || B == null) return false;
      
        if(A.val != B.val){
            return hasSameValueNode(A.left, B) || hasSameValueNode(A.right, B);
        }else{
            return isPartSame(A, B);
        }       
    }

    public boolean isPartSame(TreeNode A, TreeNode B){  //从两个树的根节点开始遍历这两个树,看是否有相同的部分
        if(B == null)   return true;
        if(A == null)   return false;

        if(A.val == B.val){
            return isPartSame(A.left, B.left) && isPartSame(A.right, B.right);
        }else{
            return false;
        }           
    }
}

版本3

参考题解

//java
class Solution {
    public boolean isSubStructure(TreeNode A, TreeNode B) {
        if(B==null||A==null) return false;
        if(!isSub(A,B))    //放到这个地方调用第二个函数,就可以判断除第一个相同值的节点外的其余相同值的节点
            return isSubStructure(A.left,B) || isSubStructure(A.right,B);
        return true;
    }
    public boolean isPartSame(TreeNode A, TreeNode B) {
        if(B==null) return true;
        if(A==null) return false;

        if(A.val==B.val)
            return isPartSame(A.left,B.left) && isPartSame(A.right,B.right);
        else 
            return false;
           
    }
}

作者:orangex
链接:https://leetcode-cn.com/problems/shu-de-zi-jie-gou-lcof/solution/tao-wa-ta-lai-liao-jing-pin-tu-jie-by-orangex/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

版本4

//java   3的代码优化
class Solution {
    public boolean isSubStructure(TreeNode A, TreeNode B) {
        if (A == null || B == null) return false;
        return DFS(A,B) || isSubStructure(A.left,B) || isSubStructure(A.right,B);
    }

    public boolean DFS(TreeNode A, TreeNode B) {
        if (B == null) return true;
        if (A == null) return false;
        return A.val == B.val && DFS(A.left,B.left) && DFS(A.right,B.right);
    } 
}

作者:le-ge-zhi-shang
链接:https://leetcode-cn.com/problems/shu-de-zi-jie-gou-lcof/solution/100ji-bai-di-gui-shen-du-you-xian-sou-suo-by-le-ge/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

面试题27.二叉树的镜像(226)

在这里插入图片描述

安安题解:递归 新建了一棵树

//java 安安 2020.4.3
//安安思路;又新建了一棵树,遍历原树时,将原树左右子树的值交换作为新树左右子树节点的值
class Solution {
    public TreeNode mirrorTree(TreeNode root) {
        if(root == null) return root;

        TreeNode mroot = new TreeNode(root.val);
        inOrderTraverse(root, mroot);
        return mroot;
    }

    public void inOrderTraverse(TreeNode root, TreeNode mroot){
        if(root != null){
            mroot.val = root.val;
            if(root.left != null){
                mroot.right = new TreeNode(root.left.val);
            }
            if(root.right != null){
                mroot.left = new TreeNode(root.right.val);
            }
            inOrderTraverse(root.left, mroot.right);
            inOrderTraverse(root.right, mroot.left);
        }
    }
}

参考题解 这里的一个动画简洁明了

解1:递归 所谓的“ 一看就会 一写就废”系列

//java
class Solution {
    public TreeNode mirrorTree(TreeNode root) {
        if(root == null) return null;
        TreeNode tmp = root.left;
        root.left = mirrorTree(root.right);
        root.right = mirrorTree(tmp);
        return root;
    }
}

作者:jyd
链接:https://leetcode-cn.com/problems/er-cha-shu-de-jing-xiang-lcof/solution/mian-shi-ti-27-er-cha-shu-de-jing-xiang-di-gui-fu-/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

解2:辅助栈(或队列)

//java   辅助栈
class Solution {
    public TreeNode mirrorTree(TreeNode root) {
        if(root == null) return null;
        Stack<TreeNode> stack = new Stack<>() {{ add(root); }};
        while(!stack.isEmpty()) {
            TreeNode node = stack.pop();
            if(node.left != null) stack.add(node.left);
            if(node.right != null) stack.add(node.right);
            TreeNode tmp = node.left;
            node.left = node.right;
            node.right = tmp;
        }
        return root;
    }
}

作者:jyd
链接:https://leetcode-cn.com/problems/er-cha-shu-de-jing-xiang-lcof/solution/mian-shi-ti-27-er-cha-shu-de-jing-xiang-di-gui-fu-/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
//java  辅助队列
public TreeNode invertTree(TreeNode root) {
    if (root == null) return null;
    Queue<TreeNode> queue = new LinkedList<TreeNode>();
    queue.add(root);
    while (!queue.isEmpty()) {
        TreeNode current = queue.poll();
        TreeNode temp = current.left;
        current.left = current.right;
        current.right = temp;
        if (current.left != null) queue.add(current.left);
        if (current.right != null) queue.add(current.right);
    }
    return root;
}

作者:LeetCode
链接:https://leetcode-cn.com/problems/invert-binary-tree/solution/fan-zhuan-er-cha-shu-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

面试题28.对称的二叉树(101)

在这里插入图片描述

在这里插入图片描述

递归法:版本1

//java anan 2020.4.3
class Solution {
    public boolean isSymmetric(TreeNode root) {
        if(root == null) return true;  //[]
        return isSymmetricOfTwoTrees(root.left, root.right);
    }

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

    }
}

递归法:版本2

//java
class Solution {
    public boolean isSymmetric(TreeNode root) {
        if(root == null) return true;  //[]
        return isSymmetricOfTwoTrees(root.left, root.right);
    }

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

递归法:版本3

//java
class Solution {
    public boolean isSymmetric(TreeNode root) {
        if(root == null) return true;  //[]
        return isSymmetricOfTwoTrees(root.left, root.right);
    }

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

递归法:别人家的

在这里插入图片描述

//java
public boolean isSymmetric(TreeNode root) {
    return isMirror(root, root);
}

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

作者:LeetCode
链接:https://leetcode-cn.com/problems/symmetric-tree/solution/dui-cheng-er-cha-shu-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

迭代法:错误版本

//java 本来想着 空的不加进去了 结果过不了
 //[1,2,2,null,3,null,3] 这个案例不能通过
class Solution {
    public boolean isSymmetric(TreeNode root) {
        if(root == null) return true;  //[]
        Queue<TreeNode> queue = new LinkedList<>();

        queue.add(root);
        queue.add(root);
        while(!queue.isEmpty()){
            TreeNode q1 = queue.poll();
            TreeNode q2 = queue.poll();
            if(q1.val != q2.val)  return false;
            if(q1.left != null) queue.add(q1.left);
            if(q2.right != null) queue.add(q2.right);
            if(q1.right != null) queue.add(q1.right);
            if(q2.left != null) queue.add(q2.left);
        }
        return true;
    }
}

迭代法:正确版本

//java 正确版本
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;
}

作者:LeetCode
链接:https://leetcode-cn.com/problems/symmetric-tree/solution/dui-cheng-er-cha-shu-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

面试题33.二叉搜索树的后序遍历序列

在这里插入图片描述

安安

//java  2020.4.6 anan 看了思路自己写的
class Solution {
    public boolean verifyPostorder(int[] postorder) {
        if(postorder.length == 1 || postorder.length == 0)   return true;   //特殊输入:[]

        int rootVal = postorder[postorder.length-1];
        int index = -1;  //划分左右子树的下标 右子树第一个节点的下标

        //找划分左右子树的下标
        for(int i=0; i < postorder.length-1; i++){
            if(postorder[i] > rootVal){
                index = i;
                break;
            }           
        }
        
        //找到这个划分下标以后 从这个下标之后遍历的值都比根节点要大  
        //若没有找到这个下标,说明最后一个值前面的值都比root的值要小
        if(index != -1){
            for(int i = index; i < postorder.length-1; i++){
                if(postorder[i] < rootVal)   return false;
            }
        }       

        //index==0 表示只有右子树
        //index==-1表示只有左子树
        //另外一个表示左右子树都有
        if(index == 0) return verifyPostorder(Arrays.copyOfRange(postorder, index, postorder.length-1));
        else if(index == -1)  return verifyPostorder(Arrays.copyOfRange(postorder, 0, postorder.length-1));
        else return verifyPostorder(Arrays.copyOfRange(postorder, 0, index))  && verifyPostorder(Arrays.copyOfRange(postorder, index, postorder.length-1));
    }

}

别人:一直用同一个数组,通过下标进行操作

//java
class Solution {
    public boolean verifyPostorder(int [] postorder) {
        if (postorder.length <= 2) return true;
        return verifySeq(postorder, 0, postorder.length-1);
    }
    private boolean verifySeq(int[] postorder, int start, int end) {
        if (start >= end) return true;
        int i;
        for (i = start; i < end; i++) {
            if (postorder[i] > postorder[end]) break;
        }
        // 验证后面的是否都大于sequence[end]
        for (int j = i; j < end; j++) {
            if (postorder[j] < postorder[end]) return false;
        }
        return verifySeq(postorder, start, i-1) && verifySeq(postorder, i, end-1);
    }
}

单调栈

题解
另一题解

//java
class Solution {
    public boolean verifyPostorder(int[] postorder) {
        // 单调栈使用,单调递增的单调栈
        Deque<Integer> stack = new LinkedList<>();
        // 表示上一个根节点的元素,这里可以把postorder的最后一个元素root看成无穷大节点的左孩子
        int pervElem = Integer.MAX_VALUE;
        // 逆向遍历,就是翻转的先序遍历
        for (int i = postorder.length - 1;i>=0;i--){
            // 左子树元素必须要小于递增栈被peek访问的元素,否则就不是二叉搜索树
            if (postorder[i] > pervElem){
                return false;
            }
            while (!stack.isEmpty() && postorder[i] < stack.peek()){
                // 数组元素小于单调栈的元素了,表示往左子树走了,记录下上个根节点
                // 找到这个左子树对应的根节点,之前右子树全部弹出,不再记录,因为不可能在往根节点的右子树走了
                pervElem = stack.pop();
            }
            // 这个新元素入栈
            stack.push(postorder[i]);
        }
        return true;
    }
}

作者:burning-summer
链接:https://leetcode-cn.com/problems/er-cha-sou-suo-shu-de-hou-xu-bian-li-xu-lie-lcof/solution/dan-diao-di-zeng-zhan-by-shi-huo-de-xia-tian/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

面试题34.二叉树中和为某一值的路径(113)

该题和自己之前做的dfs回溯合集很相似

题目
在这里插入图片描述

版1

//java  anan 2020.4.6
class Solution {
    //List<List<Integer>> res = new List<List<Integer>>();  //new的是具体的实现类
    List<List<Integer>> res;  
    int sum;
    public List<List<Integer>> pathSum(TreeNode root, int sum) {
        this.sum = sum;
        res = new ArrayList<>();
        if(root == null)  return res;  //特殊案例:[]

        List<Integer> list = new ArrayList<Integer>(){};
        list.add(root.val);
        helper(root, list, root.val);
        return res;
    }

    public void helper(TreeNode root, List<Integer> list, int sumPath){
        //System.out.println(root.val + " " + sumPath + " " + list);
        if(root.left == null && root.right == null){
            if(sumPath == sum){
                //res.add(list); 
                //若用此方式,将list直接添加进去,是将list对象添加进去了,后序list发生变化时,res里的值也会跟着发生变化
                res.add(new ArrayList<>(list));
                return ;
            }
        }

        if(root.left != null){
            list.add(root.left.val);
            helper(root.left, list, sumPath+root.left.val);
            list.remove(list.size()-1);
        }

        if(root.right != null){
            list.add(root.right.val);
            helper(root.right, list, sumPath+root.right.val);
            list.remove(list.size()-1);
        }
    }
}

需要注意的点:
1.res.add(new ArrayList<>(list)); 要新建一个对象进行添加,不能直接添加原对象
2. List list 这个可以作为全局的,应为至始至终都只对这个对象进行操作
3. //List<List> res = new List<List>(); //new的是具体的实现类
res = new ArrayList<>();
4.自己只在树节点值不为0时才递归 这样代码会比较冗长
5.自己是从0开始加的 其实也可以考虑相减 递归一次减一些

版2

//java
class Solution {
    List<List<Integer>> res;  
    List<Integer> list;
    int sum;
    public List<List<Integer>> pathSum(TreeNode root, int sum) {
        this.sum = sum;
        res = new ArrayList<>();
        list = new ArrayList<Integer>(){};

        helper(root, 0);
        return res;
    }

    public void helper(TreeNode root, int sumPath){
        if(root == null)  return ; 
        sumPath+=root.val;
        list.add(root.val);
        //System.out.println(level + " " + root.val + " " + sumPath + " " + list);
        
        if(root.left == null && root.right == null && sumPath == sum){
            res.add(new ArrayList<>(list));  
        }

        helper(root.left, sumPath);
        helper(root.right, sumPath);
        list.remove(list.size()-1);
    }
}

版3:别人家的

class Solution {
    LinkedList<List<Integer>> res = new LinkedList<>();
    LinkedList<Integer> path = new LinkedList<>(); 
    public List<List<Integer>> pathSum(TreeNode root, int sum) {
        recur(root, sum);
        return res;
    }
    void recur(TreeNode root, int tar) {
        if(root == null) return;
        path.add(root.val);
        tar -= root.val;
        if(tar == 0 && root.left == null && root.right == null)
            res.add(new LinkedList(path));
        recur(root.left, tar);
        recur(root.right, tar);
        path.removeLast();
    }
}

作者:jyd
链接:https://leetcode-cn.com/problems/er-cha-shu-zhong-he-wei-mou-yi-zhi-de-lu-jing-lcof/solution/mian-shi-ti-34-er-cha-shu-zhong-he-wei-mou-yi-zh-5/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
/*
// Definition for a Node.
class Node {
    public int val;
    public Node left;
    public Node right;

    public Node() {}

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

    public Node(int _val,Node _left,Node _right) {
        val = _val;
        left = _left;
        right = _right;
    }
};
*/


class Solution {
    Node leftMax = root;
    Node rightMin = root;
    public Node treeToDoublyList(Node root) {
        
        helper(root, leftMax, root);
        return leftMax;
    }

    public void helper(Node root, Node leftMax, Node rightMin){
        if(root.left == null && root.right == null){     //叶子节点
            // leftMax = (root.val < leftMax.val) ? root : leftMax;
            // rightMin = (root.val > rightMin.val) ? root : rightMin;
            leftMax = root;
            rightMin = root;
            System.out.println("**leftMax.val:" + leftMax.val + " root.val:" + root.val);
            System.out.println("**rightMin.val:" + rightMin.val + " root.val:" + root.val);
            return;
        }

        if(root.left != null){
            helper(root.left, leftMax, rightMin);
            System.out.println("leftMax.val:" + leftMax.val + " root.val:" + root.val);
            leftMax.right = root;
            root.left = leftMax;
            
        }
                       
        if(root.right != null){
            helper(root.right, leftMax, rightMin);
            System.out.println("rightMin.val:" + rightMin.val + " root.val:" + root.val);
            root.right = rightMin;
            rightMin.left = root;
            
        }      
    }    
}

面试题36.二叉搜索树和双向链表(426)

题目
在这里插入图片描述
在这里插入图片描述

版本1

题解

//这个同学的版本比我自己写的那个简洁许多,但是这个新建了一个节点
class Solution {
    Node pre = new Node(0), head = pre;
    public Node treeToDoublyList(Node root) {
        if(root == null) return null;
        dfs(root);
        head = head.right;
        head.left = pre;
        pre.right = head;
        return head;
    }
    void dfs(Node cur) {
        if(cur == null) return;
        dfs(cur.left);
        pre.right = cur;
        cur.left = pre;
        pre = cur;
        dfs(cur.right);
    }
}

作者:jyd
链接:https://leetcode-cn.com/problems/er-cha-sou-suo-shu-yu-shuang-xiang-lian-biao-lcof/solution/mian-shi-ti-36-er-cha-sou-suo-shu-yu-shuang-xian-5/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

版本2

题解

class Solution {
    Node head=null,pre=null,tail=null;
    public Node treeToDoublyList(Node root) {
        if(root==null) return root;
        //中序遍历访问节点并连接
        inorder(root);
        //连接头尾节点
        head.left=tail;
        tail.right=head;
        return head;
    }
    private void inorder(Node root){
        //递归出口
        if(root==null) return ;
        //访问左子树
        inorder(root.left);
        //将当前节点和上一个节点连接
        if(pre==null) head=root;
        else pre.right=root;
        root.left=pre;
        pre=root;
        tail=root;
        //访问右子树
        inorder(root.right);
        return ;
    }
}

作者:chenjunboBUPT
链接:https://leetcode-cn.com/problems/er-cha-sou-suo-shu-yu-shuang-xiang-lian-biao-lcof/solution/zhong-xu-bian-li-fang-wen-jie-dian-quan-ju-bian-li/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
//java  没有新建节点,都是在原节点上进行操作
//参考上述题解 进行了部分更改
class Solution {
    Node pre;
    Node head;

    public Node treeToDoublyList(Node root) {
        if(root == null)  return root;
       
        helper(root);   //遍历结束后,pre是最后一个节点
        head.left = pre;
        pre.right = head;
        return head;
    }

    public void helper(Node root){
        if(root == null)  return;

        helper(root.left);

        if(pre == null){
            pre = root;
            head = root;
        }else{
            pre.right = root;
            root.left = pre;
            pre = root;
        }

        helper(root.right);           
    }   
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

安安csdn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值