代码随想录刷LeetCode | 二叉树深度优先遍历刷题回顾

前沿:撰写博客的目的是为了再刷时回顾进一步完善,其次才是以教为学,所以如果有些博客写的较简陋,是为了保持进度不得已而为之,还请大家多多见谅。

预:看到题目后的思路和实现的代码。

见:参考答案展示。

感思:对比答案后的思考,与之前做过的题目是否有关联。

行:

(1)对于没做出来的题目,阅读答案后重新做一遍;

(2)下次做题可以尝试改善的方向;

(3)有助于理解的相关的题目

通过默写题目思路来判断对每道题真实的掌握情况,只有了解客观的做题情况,才能有效地发现问题去解决。

题目回顾

1. 二叉树理论基础

1.1问题导向学习二叉树

(1)为什么要有二叉树?

便于查找搜索模拟树的结构?二叉树类似计算机0-1,效率高?也有图结构分别应用场景是什么?

图结构考虑到左右相邻的关系,而树结构更多的是父与子的关系,二叉树即至多只有两个孩子。

孩子的少,则数据量大时深度大,而二叉树的搜索能力类似归并算法,所以遍历效率是否会被影响?

二叉树类似“兄弟-孩子”的关系,一个连兄弟(有区别),一个连儿子(传承),这样仍有判断归类的功能。同时能最大限度的节省空间,而三个节点或更多子节点的结构则会相对消耗更多内存。

在实际应用中,平衡二叉树搜索较为稳定,相对于散列表,其是有序的,并且效率不一定比散列表慢散列表可能会出现哈希冲突,所以搜索效率也会受影响,并且解决的方式考虑不好会消耗更多地内存。

平衡二叉树即保证左右层差<2

(2)二叉树存储

链表(常使用)和数组(父节点数组下标是 i,它的左孩子 i * 2 + 1,右孩子 i * 2 + 2)

(3)二叉树遍历方式

二叉树遍历分为深度优先遍历(DFS)和广度优先遍历(BFS)。

  1. 深度优先遍历的实现方式:递归(也可用栈实现) and 迭代
    1. 深度优先遍历又分为前中后序遍历,其前中后都指的是中节点的位置,像深度前序优先遍历是按照中左右节点进行遍历。
  2. 广度优先遍历实现方法迭代,可使用队列实现。

面试手撕代码,所以数据结构的定义以及简单逻辑的代码一定要锻炼白纸写出来。

1.2二叉树相关概念:

(1)满二叉树

  • 全部都子女双全;每层节点为0或2,总长度为2^k-1。

(2)完全二叉树

  • 前面n层节点跟满二叉树一样,最后一层节点长度为1~2^(k-1),按照顺序从左到右增加。

(3)搜索二叉树

  • 所有的左子树上的节点<根节点,所有的右子树上的节点>根节点,
  • 要注意左子树的右子节点<根节点,同理右节点的左子节点>根节点。

(4)平衡二叉树

  • 左右节点相差高度为1以内,其时间复杂度为logn可作为判断复杂度的指标;像set、map等采用平衡二叉树作为底层,而un_set\un_map则是哈希。

2. 递归遍历(必须掌握)

递归三元素实现递归的步骤:

  • 确定递归函数的传入类型值返回值
  • 确定单层递归的逻辑
  • 确定递归函数的终止条件

题目链接:144. 二叉树的前序遍历

前序遍历顺序:中左右

1.递归函数:无需返回值,传入(TreeNode root,List<Integer> result)

2.单层递归的逻辑:将当前节点值存入result里;递归函数传入左节点;递归函数传入右节点;

3.递归函数的终止条件:当前节点为空时,返回

题目链接:94. 二叉树的中序遍历

中序遍历顺序:左中右

1.递归函数与终止条件同上

2.单层递归的逻辑:递归函数传入左节点;将当前节点值存入result里;递归函数传入右节点;

题目链接:145. 二叉树的后序遍历

1.递归函数与终止条件同上

2.单层递归的逻辑:递归函数传入左节点;递归函数传入右节点;将当前节点值存入result里

3.94. 二叉树的中序遍历(迭代)

题目链接:94. 二叉树的中序遍历

3.1二刷做不出原因分析

二刷知道要使用栈先进后出的特性实现,思考15分钟,没有想出来跳过

当时分析做不出来的原因:遍历左边后如何再回溯遍历右边节点?

思路:通过创建临时当前节点+出栈时把值赋予cur以此来遍历右节点。

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        //二叉树的迭代遍历;中序遍历:左中右:栈实现
        List<Integer> result = new LinkedList<>();
        if(root == null){
            return result;
        }
        Deque<TreeNode> deque = new LinkedList<>();
        TreeNode cur = root.left;
        deque.push(root);
        while(cur != null || !deque.isEmpty()){
            if(cur != null){
                deque.push(cur);
                cur = cur.left;
            }else{
                cur = deque.peek();
                deque.pop();
                result.add(cur.val);
                cur = cur.right;
            }
        }
        return result;
    }
}

前序遍历顺序:中左右

1.使用栈stack(先进后出)poppush存入当前节点,while循环终止条件为stack不为空;

2.TreeNode tNode = stack.pop();将栈弹出,并将弹出值赋予tNode临时变量。

3.将tNode值存入结果,并依次判断右左(弹出时则反过来)节点是否存在,若存在则存入栈。

4. 145. 二叉树的后序遍历(统一迭代)

题目链接:145. 二叉树的后序遍历

思路:统一迭代(标记)法

  • 前序遍历顺序:中左右
  • 与迭代遍历区别:通过空白作为遍历的输出信号

1步骤同上

2.TreeNode tNode = stack.peek();将栈弹出栈顶不出栈,并将值赋予tNode临时变量。

3.判断tNode是否为空:

  • tNode不为空:
    • stack.pop()弹出当前节点
    • 依次判断右左(弹出时则反过来)节点是否存在,若存在则存入栈。
    • 再依次存入当前节点和空白入栈。
  • tNode为空:
    • stack.pop()弹出当前节点(弹出的为空白节点)
    • 并将此时的tNode值存入result中
    • 最终再弹出当前节点(弹出的为存入结果节点)
class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        //二叉树的统一迭代遍历:左右中
        List<Integer> result = new LinkedList<>();
        if(root == null){
            return result;
        }
        Deque<TreeNode> deque = new LinkedList<>();
        TreeNode node = new TreeNode();
        deque.push(root);
        while(!deque.isEmpty()){
            if(deque.peek() != null){
                node = deque.peek();
                deque.push(null);
                if(node.right != null){
                    deque.push(node.right);
                }
                if(node.left != null){
                    deque.push(node.left);
                }
            }else{
                deque.pop();
                //node = deque.pop();
                result.add(deque.pop().val);
            }
        }
        return result;
    }
}

相关知识点:

stack.pop与stack.peek()区别:

  1. pop()出栈(先进后出)
  2. peek() 查看栈顶元素,但不出栈。

一刷时的总结

耗时一小时大体完成了二叉树一天的刷题总结

  • 70%时间投入到看题默写思路上面,20%时间投入到对比答案上面。

若是六天的刷题量按照这种进度总结,则需要6小时才能完成。所以集中时间周日回顾是不现实的压力也大,但若不默写思路,则很难确定掌握情况。

行:

是否可以每天回顾昨日的题目,然后周末只需从整体进行总结。

周末对做题过程做总结复盘,结合一到六撰写的默写题总结,分别标注出哪些题目是重要已掌握、重要未掌握、不重要已掌握、不重要未掌握,为以后再次复习做好指南,分重点来攻克。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值