LeetCode前序、中序、后序的非递归遍历,以及BST的题目

前序、中序、后序的递归解法非常好做,但是迭代的写法比较生疏,甚至可以写上一个多小时,令人害怕
BST的题目做得不是很好,感觉主要问题是脑子想不到递归该如何去解,思维混乱
序列化和反序列化这类的题目也比较生疏,虽然LeetCode上把它标为hard,但是感觉还是很常见的题目之一,一定要会做

非递归前序遍历

前序遍历其实是根左右
非递归前序遍历的思路:如果先输出遍历元素,再向栈中压入右节点,左节点,这就是前序遍历

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        Stack<TreeNode> stack = new Stack<>();
        stack.add(root);
        List<Integer> res = new ArrayList<>();
        while(!stack.isEmpty()){
            root = stack.pop();
            if(root == null) continue;
            res.add(root.val);
            stack.add(root.right);
            stack.add(root.left);
        }
        return res;
    }
}

非递归中序遍历

中序遍历是 左根右
当时写了一个小时才AC,太弱了
其实思路缕清以后发现,也不难
思路在此,只要root != null,那就将root一直压入栈中,root = root.left 如果root == null了,那就说明最左边的元素已经到头了,这个时候就从栈中弹出节点,打印这个节点,然后让root = root.right 一直循环操作,直到栈为空了

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
       Stack<TreeNode> stack = new Stack<>();
       List<Integer> res = new ArrayList<>();
       while(root != null || !stack.isEmpty()) {
           if(root != null){
               stack.add(root);
               root = root.left;
           }else{
               root = stack.pop();
               res.add(root.val);
               root = root.right;
           }
       }
       return res;
    }
    
}

非递归后序遍历

后序是 左右根
反过来是 根右左
所以就是在前序遍历的基础上,改动一下,再进行逆序即可

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        Stack<TreeNode> stack = new Stack<>();
        stack.add(root);
        List<Integer> res = new ArrayList<>();
        while(!stack.isEmpty()){
            root = stack.pop();
            if(root == null) continue;
            res.add(root.val);
            stack.add(root.left);
            stack.add(root.right);
        }
        Collections.reverse(res);
        return res;
    }
}

LeetCode669.修建二叉搜索树

LeetCode669
这道题当时并没有做出来,思路比较混乱,甚至没有思路
看了题解才做出来,觉得递归真是绝呀
在这里插入图片描述
思路在此:
1.如果node.val <L,那么说明node的左子树也全部小于L,只需要考虑node的右子树部分就行了
2.如果node.val > R,那么说明node的右子树也全部大于R,只需要考虑node的右子树部分就行了
3.如果node.val在[L,R]之间,那么就需要对左右子树同时进行修剪

我怎么就想不到呢[愤恨]

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode trimBST(TreeNode root, int L, int R) {
        if(root == null) return null;
        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;
    }
}

二叉搜索树的序列化、反序列化

不需要"null"或者"#"这些占位符,使用前序遍历、后序遍历的序列,就可以确定二叉搜索树了
对于普通的二叉树需要有这种占位符的字符串序列 或者 前序+中序 或者 后序+中序 才可以确定,因为二叉搜索树本身的中序就是知道的,所以BST只需要前序或后序遍历即可确定。

前序遍历解法

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

    // Encodes a tree to a single string.
    public String serialize(TreeNode root) {
        //编码的字符串尽可能紧凑,也就是说不需要"null"或者"#"这些占位符
        //通过一串数字就可以确定这个二叉树的模样,因为它是二叉搜索树呀
        //普通的二叉树需要有这种占位符的字符串或者前序+中序序列才可以确定
        /*---   前序遍历的解法   ---*/
        if(root == null){
            return "";
        }
        String str = String.valueOf(root.val)+",";
        str += serialize(root.left);
        str += serialize(root.right);
        return str;
    }

    // Decodes your encoded data to tree.
    public TreeNode deserialize(String data) {
        if(data.length() < 1){
            return null;
        }
        String[] str = data.split(",");
        return deserialize(new TreeNode(0),str,0,str.length);
    }
    public TreeNode deserialize(TreeNode root,String[] data,int s,int e){
        if(s < e ){
            root = new TreeNode(Integer.valueOf(data[s]));
            int i = s + 1;
            int n2 = Integer.valueOf(data[s]);
            for(i = s+1;i < e;i++){
                int n1 = Integer.valueOf(data[i]);               
                if(n1 > n2){
                    break;
                }
            }
            root.left = deserialize(root.left,data,s+1,i);
            root.right = deserialize(root.right,data,i,e);
            return root;
        }
        return null;
    }
}

// Your Codec object will be instantiated and called as such:
// Codec codec = new Codec();
// codec.deserialize(codec.serialize(root));

普通二叉树的序列化、反序列化

前序遍历
使用有占位符的字符串

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

    // Encodes a tree to a single string.
    public String serialize(TreeNode root) {
        //前序遍历
        if(root == null) return "null";
        String str = String.valueOf(root.val)+","; 
        str += serialize(root.left)+",";
        str += serialize(root.right);
        return str; 
    }

    // Decodes your encoded data to tree.
    public TreeNode deserialize(String data){
         String[] str = data.split(",");
         return mydeserialize(str,new TreeNode(0));
    }
    int point = 0;
    public TreeNode mydeserialize(String[] data,TreeNode node) {
        if(data[point].equals("null") || point >= data.length){
            point++;
            return null;
        }
        node = new TreeNode(Integer.valueOf(data[point++]));
        node.left = mydeserialize(data,node.left);
        node.right = mydeserialize(data,node.right);
        return node;
    }
}

// Your Codec object will be instantiated and called as such:
// Codec codec = new Codec();
// codec.deserialize(codec.serialize(root));

层次遍历
这里要使用StringBuilder,可以提升很大的效率

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

    // Encodes a tree to a single string.
    public String serialize(TreeNode root) {
        //层次遍历
        if(root == null){
            return "";
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        StringBuilder res = new StringBuilder("");
        while(!queue.isEmpty()){
            root = queue.poll();
            if(root == null){
                res.append("null,");
            }else{
                res.append(root.val + ",");
                queue.add(root.left);
                queue.add(root.right);
            }
        }
        //System.out.println(res);
        return res.toString();
    }

    // Decodes your encoded data to tree.
    public TreeNode deserialize(String data) {
        if(data.length() < 1){
            return null;
        }
        String[] str = data.split(",");
        Queue<TreeNode> queue = new LinkedList<>();
        TreeNode root = new TreeNode(Integer.valueOf(str[0]));
        queue.add(root);  
        int i = 1;
        while(i < str.length && !queue.isEmpty()){
            TreeNode knode = queue.poll();
            if(str[i].equals("null")){
                knode.left = null;
                i++;
            }else{
                knode.left = new TreeNode(Integer.valueOf(str[i++]));
                queue.add(knode.left);
            }   
            if(str[i].equals("null")){
                knode.right = null;
                i++;
            }else{
                knode.right = new TreeNode(Integer.valueOf(str[i++]));
                queue.add(knode.right);
            } 
        }
        
        return root;
    }
}

// Your Codec object will be instantiated and called as such:
// Codec codec = new Codec();
// codec.deserialize(codec.serialize(root));
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值