LeeCode刷题简记(七)

树、二叉树

二叉树又有特殊二叉树,完全二叉树,满二叉树

因为二叉树本身就是递归型数据结构,所以很多问题都可以用递归实现

总结递归1.当做根、左子树、右子树三部分,左子树、右子树具体是什么样的不管 2.找出终止条件,就是什么时候return,return什么 3.只考虑当前这一步要完成什么功能

Solution114二叉树展开为链表、Solution111二叉树的最小深度、Solution107二叉树的层序遍历Ⅱ、Solution104二叉树的最大深度、Solution102二叉树的层序遍历、Solution94中序遍历、Solution144前序遍历、Solution145后序遍历、

Solution114二叉树展开为链表

给你二叉树的根结点 root ,请你将它展开为一个单链表:

展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。
展开后的单链表应该与二叉树 先序遍历 顺序相同。

递归因为在操作左子树之前不能动右子树,所以用后序遍历

class Solution {
    public void flatten(TreeNode root) {
        if(root == null) {
            return;
        }
        flatten(root.left);
        flatten(root.right);
        //临时变量储存右节点
        TreeNode tmp = root.right;
        root.right = root.left;
        root.left = null;
        while(root.right != null) {
            root = root.right;
        }
        root.right = tmp;
    }
}

迭代循环方式

class Solution {
    public void flatten(TreeNode root) {
        Stack<TreeNode> stack = new Stack();
        while (root != null || !stack.isEmpty()){
            while (root != null){
                stack.push(root);
                root = root.left;
            }

            if (!stack.isEmpty()){
                TreeNode node = stack.pop();
                TreeNode tmp = node.right;
                node.right = node.left;
                node.left = null;
                
                while(node.right != null) node = node.right;
                node.right = tmp;
                root = tmp;
            }
        }
    }
}

Solution111二叉树的最小深度

给定一个二叉树,找出其最小深度。

最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

说明:叶子节点是指没有子节点的节点。

求最小深度时将Math.max换成Math.min即可,但要注意如果根节点的左或右子树为空的话是构不成子树的。而最小深度是要求从根节点到子树的。当左或右子树为空时,不符合要求。

class Solution {
    public int minDepth(TreeNode root) {
		if (root == null) {
			return 0;
		}
		int left = minDepth(root.left);
		int right = minDepth(root.right);
		return left == 0 || right == 0 ? 1 + left + right : 1 + Math.min(left, right);
	}
}

Solution107二叉树的层序遍历Ⅱ

给你二叉树的根节点 root ,返回其节点值 自底向上的层序遍历 。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)

把层序遍历Ⅰ拿来反转一下,或者如下使用LinkedList队首添加再弹出

class Solution {
    public List<List<Integer>> levelOrderBottom(TreeNode root) {
        //巧妙地利用了队列中的元素是按层排序的性质,
        //每下一层的节点入完队,下一次的 queue.size() 就是下一层的数量
        LinkedList<List<Integer>> result = new LinkedList<>();
        if (root == null)
            return result;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        while (!queue.isEmpty()) {
            List<Integer> oneLevel = new ArrayList<>();
            // 每次都取出一层的所有数据
            int count = queue.size();
            for (int i = 0; i < count; i++) {
                TreeNode node = queue.poll();
                oneLevel.add(node.val);
                if (node.left != null)
                    queue.add(node.left);
                if (node.right != null)
                    queue.add(node.right);
            }
            // 每次都往队头塞
            result.addFirst(oneLevel);
        }
        return result;
    }
}

Solution104二叉树的最大深度

给定一个二叉树,找出其最大深度。

二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

 递归实现比较简单

//递归
    public int maxDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }
        int left = maxDepth(root.left);
        int right = maxDepth(root.right);
        return Math.max(left, right) + 1;
    }

Solution102层序遍历

队列实现:思想为先头再左右,挨个出队,谁出队谁左右进队

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> ret = new ArrayList<List<Integer>>();
        // 首先判断根节点非空
        if (root == null) {
            return ret;
        }    
        // 定义队列
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        // 初始根节点入队
        queue.add(root);
        // 用于存储该层节点数值
        List<Integer> level = new ArrayList<Integer>();
        // 队列非空循环
        while (!queue.isEmpty()) {
            // 每轮出队该层的全部节点,提前记录该层节点个数,队列会变
            int cur = queue.size();
            for (int i = 1; i <= cur; ++i){
                TreeNode node = queue.poll();
                level.add(node.val);
                // 如果左右孩子非空则入队
                if (node.left != null) {
                    queue.add(node.left);
                }
                if (node.right != null) {
                    queue.add(node.right);
                }
            }
            // 添加该层节点数值列表到结果
            ret.add(level);
        }
        return ret;
    }
}

前中后序遍历

while( 栈非空 || p 非空){
   if( p 非空){}
   else{}
}

照这个模板想,迭代方式一步一步来

public class Solution前后中序遍历 {
    public class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;

        TreeNode() { }

        TreeNode(int val) {
            this.val = val;
        }

        TreeNode(int val, TreeNode left, TreeNode right) {
            this.val = val;
            this.left = left;
            this.right = right;
        }
    }

    //前序
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList();
        Stack<TreeNode> stack = new Stack();
        TreeNode cur = root;
        while(cur!=null || !stack.isEmpty()){
            //一直往左压入栈
            while(cur!=null){
                list.add(cur.val);
                stack.push(cur);
                cur = cur.left;
            }
            cur = stack.pop();
            cur = cur.right;
        }
        return list;
    }

    //后序
    public List<Integer> postorderTraversal(TreeNode root) {
        Stack<TreeNode> stack = new Stack<>();
        List<Integer> list = new ArrayList<>();
        TreeNode cur = root;
        TreeNode p = null;//用来记录上一节点
        while(!stack.isEmpty() || cur != null){
            while(cur != null){
                stack.push(cur);
                cur = cur.left;
            }
            cur = stack.peek();
            if(cur.right == null || cur.right == p){
                list.add(cur.val);
                stack.pop();
                p = cur;
                cur = null;
            }else{
                cur = cur.right;
            }
        }
        return list;
    }

    //中序
    public List<Integer> inorderTraversal(TreeNode root) {
        Stack<TreeNode> stack = new Stack<>();
        List<Integer> list = new ArrayList<>();
        while (root != null || !stack.isEmpty()) {
            if (root != null) {
                stack.push(root);
                root = root.left;
            } else {
                root = stack.pop();
                list.add(root.val);
                root = root.right;
            }
        }
        return list;
    }
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值