暑期LeetCode打卡(Week3)——树专题(递归-非递归)

刷题时间:2019/04/19 – 2019/04/20
主播:yxc(闫雪灿)
视频链接:https://v.douyu.com/show/qJgOWxKRjeeMkVzL

题号题目链接
87Scramble Stringhttps://leetcode.com/problems/scramble-string/
95Unique Binary Search Trees IIhttps://leetcode.com/problems/unique-binary-search-trees-ii/
113Path Sum IIhttps://leetcode.com/problems/path-sum-ii/
106Construct Binary Tree from Inorder and Postorder Traversalhttps://leetcode.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/
107Binary Tree Level Order Traversal IIhttps://leetcode.com/problems/binary-tree-level-order-traversal-ii/
112Path Sumhttps://leetcode.com/problems/path-sum/
110Balanced Binary Treehttps://leetcode.com/problems/balanced-binary-tree/
101Symmetric Treehttps://leetcode.com/problems/symmetric-tree/
104Maximum Depth of Binary Treehttps://leetcode.com/problems/maximum-depth-of-binary-tree/
145Binary Tree Postorder Traversalhttps://leetcode.com/problems/binary-tree-postorder-traversal/
105Construct Binary Tree from Preorder and Inorder Traversalhttps://leetcode.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/
331Verify Preorder Serialization of a Binary Treehttps://leetcode.com/problems/verify-preorder-serialization-of-a-binary-tree/
102Binary Tree Level Order Traversalhttps://leetcode.com/problems/binary-tree-level-order-traversal/
653Two Sum IV - Input is a BSThttps://leetcode.com/problems/two-sum-iv-input-is-a-bst/
236Lowest Common Ancestor of a Binary Treehttps://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/
543Diameter of Binary Treehttps://leetcode.com/problems/diameter-of-binary-tree/
124Binary Tree Maximum Path Sumhttps://leetcode.com/problems/binary-tree-maximum-path-sum/
94Binary Tree Inorder Traversalhttps://leetcode.com/problems/binary-tree-inorder-traversal/
114Flatten Binary Tree to Linked Listhttps://leetcode.com/problems/flatten-binary-tree-to-linked-list/
226nvert Binary Treehttps://leetcode.com/problems/invert-binary-tree/
617Merge Two Binary Treeshttps://leetcode.com/problems/merge-two-binary-trees/
144Binary Tree Preorder Traversalhttps://leetcode.com/problems/binary-tree-preorder-traversal/
538Convert BST to Greater Treehttps://leetcode.com/problems/convert-bst-to-greater-tree/
108Convert Sorted Array to Binary Search Treehttps://leetcode.com/problems/convert-sorted-array-to-binary-search-tree/
230Kth Smallest Element in a BSThttps://leetcode.com/problems/kth-smallest-element-in-a-bst/

LeetCode

解题心得

No.87 扰乱字符串 (AC)

  • 递归来做。
  • 分别按每一位切分,看切分前后的两段能否匹配。
  • 时间复杂度为O(5^n)

No.95 打印所有可能的二叉树 (AC)

  • 本题的总体思路是递归解决。对于每一个小区间,依次枚举每个位置上的数为当前根结点,然后递归求出它左右子树的所有可能组合形式,以vector<TreeNode*>的形式返回。然后两层循环当前左子树的所有组合的集合和右子树的所有组合的集合,分别作为当前根结点的左右子树,并把结果放到答案中返回。
  • 本题按照自己的思维方式,很容易写出bug:
for (int i = l; i <= r; i++){
            // TreeNode* t = new TreeNode(i);  // Bug写法
            vector<TreeNode*> left = dfs(l, i - 1);
            vector<TreeNode*> right = dfs(i + 1, r);
            // TreeNode* t = new TreeNode(i);  // Bug写法
            for (auto l : left){
                for (auto r : right){
                    TreeNode* t = new TreeNode(i);
                    t->left = l;
                    t->right = r;
                    ans.push_back(t);
                }
            }
        }

No.113 路径之和 (AC)

  • 注意回溯过程。dfs网下走一层后,回溯时需要将加到路径中的只弹出来。vector<int> path 弹出末尾元素的方法: 1. path.erase(path.end() - 1); 2. path.pop_back();
  • 对于叶节点的判断方式:if(!root->left ** !root->right)

No.106 根据中序和后序重建二叉树 (AC)

  • 本题和105题类似
  • 区间建议写成闭区间,写对递归区间是本题的关键。

No.107 翻转层序遍历结果 (AC)

  • 层序遍历二叉树,然后将结果翻转。

No.112 判断二叉树中是否存在路径等于指定值 (AC)

  • 这里的路径是指从根结点到叶节点的一条完整路径。
  • 对于叶节点的判断是易错点,应该写成:if(!root->left && !root->right)

No.110 判断是否为平衡二叉树 (AC)

  • 需要满足:每个子节点的左右子树的高度差不超过1

No.101 判断一个数是否对称 (AC)

  • 递归来做
  • 非递归方法来做,用两个辅助栈存储左右子树中的节点。这种方法还不熟。

No.104 求二叉树的最大深度 (AC)

  • 递归

No.145 输出树的后续遍历 (AC)

  • 递归来做

No.105 根据先序还中序构建树 (AC)

  • 根据先序将先序和中序序列划分成左右子树和根。根据根节点的值构建一个新(根)结点,然后根节点的左右字数用递归方法构建。
  • 需要特别注意的是,dfs中左右子树的起始位置。
  • 这里还有一个技巧,中序序列可以用一个哈希表记录,这样就可以在O(1)的时间内找到某个值的位置。

No.331 判断一个前序序列能否构成一棵树 (AC)

  • 从前往后遍历,碰到‘#’后表示到达一个叶结点,返回。
  • 若还未完成一棵正常树的构建,则返回false;
  • 最终没有被判false,且最终遍历的索引位置正好是序列的末尾,则是一个合法的树前序序列。
  • 处理上还有一个技巧,在先序序列的末尾加一个 ‘,’ ,可以使情况更简单,详见代码。

No.102 层序打印二叉树 (AC)

  • BFS问题
  • 用一个队列来存放树中的结点。每一层末尾添加一个nullptr表示结束。这样容易写出死循环,当队列中只剩一个nullptr是跳出循环,并把最后一层的值放到最后的答案中。

No.653 判断搜索二叉树中是否存在两个数和为sum (AC)

  • 根据二叉树的特性,先中序遍历得到一个升序数组,然后双指针解决。
  • 双指针找sum时应注意,i < j 这个条件要时时满足

No.236 寻找两个结点的最低公共祖先 (AC)

  • 可以写成一个自递归
  • 当前结点若为p, q中的任意一个,则返回当前结点,否则返回空。其实在递归处理时,最先处理的是叶结点,所以上诉两种情况都是返回当前结点本身。
  • 递归处理完左右结点之后,如何更新他们的父节点是关键。
  • 根据题意,我们可以肯定一定存在最低公共祖先,所以要么是根节点,要么在左子树,要么在右子树中。所以在更新父节点时,如果左子树遍历结果为空,则返回右子树遍历的结果;若右子树遍历的结果为空,则返回左子树的遍历结果;若左右子树都不是空,则返回他们父节点的值。这里需要说明的一点是。如果左右子树中都不包含目标节点(为空),那么不论返回左子树遍历结果还是右子树遍历结果其实都是空。

No.543 求二叉树的直径 (AC)

  • dfs来做。
  • 在遍历每一个结点的时候,记录以它为根节点的深度和最大长度(深度/左子树长度+右子树长度+ 1)。
  • 自己的方法是每次遍历时返回一个pair,分别记录数的深度和当前的最大值。
  • 简化代码的话,可以用一个全局变量来记录数的最大长度(直径)。

No.124 二叉树中连续序列和最大是多少 (AC)

  • dfs来做,思路和上一题比较相似
  • 用一个全局变量记录最大值,在每一次遍历的时候更新
  • dfs的返回值是当前子树的单分支的最大值,这样能够保证序列是连续
  • 还有一点需要注意,更新最大值ans时,为ans = root->val + left + right;,这里若left或right为负数则不应做加法,为了避免讨论,递归求得的**left和right的值和0取一个max,**这样可以减少很多麻烦。
  • 一开始自己的方法就对left和right的正负做了讨论,用了很多max函数,其实用上一条的方法就可以避免。自己的方法中还有一个问题是,求得最大值所用到的序列可能不是连续的。

No. 94 二叉树的中序遍历(AC)

  • 二叉树的前序,中序和后序遍历的递归循环写法要熟悉
  • 前序和中序的循环形式比较简单,后序的循环写法还要记录一个last结点。

No.114 把二叉树原地转换成右链 (AC)(划重点)

  • 当前结点存在左子树时,先定位到左子树的根节点,然后找到左子树最右侧的结点,并到右链中,然后遍历二等指针往后移一步,指导所有结点都并到右链上。

NO.226 翻转二叉树 (AC)

  • 本题考虑递归和非递归两种方式来做。
  • 非递归的方法类似于层序遍历的方法,用一个双端队列deque来辅助翻转

No.617 Merge Two Binary Trees (AC)

  • 递归的方法做。注意特判为空的情况。

No.144 二叉树前序遍历 (AC)

  • 递归和非递归两种方式

No.538 将搜索二叉树变成更大二叉树 (AC)

  • 后序遍历的思想
  • 可以递归实现
  • 需要注意的一点是,实现的时候要注意不要让二叉树最右边的结点加上本身的值,最右侧的结点是最大的结点,应该是加上0。

No.108 将排序数组转换成搜索二叉树 (AC)

  • 此题中转换答案不唯一,可以选择一种复合题意的方式转换
  • 将数组最中间的位置作为根节点,然后左右两边的数组元素作为左右子树中的结点,递归来做。

No.230 找到搜索二叉树的第K大结点 (AC)

  • 中序遍历得到一个上升序列,取第K个元素即可。
  • 需要注意的是,k <= 0 和 k > len的边界处理。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值