• 二叉树相关OJ题目复习总结


    最近开始复习了,疫情影响又要延迟开学,趁着这几天好好复习一下下,把二叉树的一些OJ题做做总结,权当练习代码能力,一个暑假数学建模培训占了好长时间,后面赶正式开学前抓紧复习吧!!!

    二叉树中最近公共祖先https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/

     题目分析:

    1、假设这棵树是双亲表示法(包含双亲的信息)——链表的思路

     求最近公共祖先,其实又是求两个链表的交点。

    2、假设这棵树是二叉搜索树(排序树)_左子树比右子树小

     求最近公共祖先

    1. //1.
    2. p==root || q==root //此时最近公共祖先是root;
    3. //2.
    4. p.val < root.val && q.val > root.val  || p.val > root.val && q.val < root.val
    5. //  p在左          q在右                   p在右               q在左
    6. //此时根节点root就是最近公共祖先;
    7. //3.
    8. p.val < root.val && q.val
    9. //此时说明p和q都在root的左子树当中,此时需要递归到左子树上。
    10. //4.
    11. p.val > root.val && q.val > root.val
    12. // 此时说明p和q都在root的右子树当中,此时需要递归到右子树上。

     

    最终的代码:

    1. class Solution {
    2. public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
    3. if(root == null){
    4. return null;
    5. }
    6. if(root == p || root == q){
    7. return root;
    8. }
    9. TreeNode retLeft = lowestCommonAncestor(root.left,p,q);
    10. TreeNode retRight = lowestCommonAncestor(root.right,p,q);
    11. if(retRight != null && retLeft != null){
    12. return root;
    13. }else if(retLeft != null){
    14. return retLeft;
    15. }else{
    16. return retRight;
    17. }
    18. }
    19. }

    3.申请两个栈空间来进行判断最近公共祖先(栈的思路)

    先判断两个栈的大小,将大栈减到与小栈大小相等来进行 一 一比较,当相同时找到最近公共祖先。

    栈思路的难点就是 如何找到 根节点 到 指定节点的路径,存到栈当中?

     该思路代码:

     

    1. class Solution {
    2. public TreeNode lowestCommonAncestor(TreeNode root,TreeNode p, TreeNode q) {
    3. if(root == null || p == null || q == null) {
    4. return null;
    5. }
    6. Stack stack1 = new Stack<>();
    7. getPath(root,p,stack1);
    8. Stack stack2 = new Stack<>();
    9. getPath(root,q,stack2);
    10. int size1 = stack1.size();
    11. int size2 = stack2.size();
    12. if(size1 > size2) {
    13. int tmp = size1-size2;
    14. while (tmp != 0) {
    15. stack1.pop();
    16. tmp--;
    17. }
    18. }else {
    19. int tmp = size2-size1;
    20. while (tmp != 0) {
    21. stack2.pop();
    22. tmp--;
    23. }
    24. }
    25. //两个栈当中 元素的个数是一样的
    26. while (!stack1.empty() && !stack2.empty()) {
    27. if(stack1.peek() == stack2.peek()) {
    28. return stack1.peek();
    29. }else {
    30. stack1.pop();
    31. stack2.pop();
    32. }
    33. }
    34. return null;//没有公共祖先
    35. }
    36. /**
    37. * 找到根节点到指定节点node之间路径上的所有节点,存储到stack当中
    38. * @param root
    39. * @param node
    40. * @param stack
    41. */
    42. private boolean getPath(TreeNode root, TreeNode node,
    43. Stack stack) {
    44. if(root == null || node == null) {
    45. return false;
    46. }
    47. stack.push(root);
    48. if(root == node) {
    49. return true;
    50. }
    51. boolean ret1 = getPath(root.left,node,stack);
    52. //不能判断false的问题,因为此时只能证明左边不存在
    53. if(ret1) {
    54. return true;
    55. }
    56. boolean ret2 = getPath(root.right,node,stack);
    57. if(ret2) {
    58. return true;
    59. }
    60. // 根节点不是 跟的左边没找到 根的右边没找到
    61. stack.pop();
    62. return false;
    63. }
    64. }

    二叉搜索树与双向链表icon-default.png?t=M7J4https://www.nowcoder.com/practice/947f6eb80d944a84850b0538bf0ec3a5?tpId=13&&tqId=11179&rp=1&ru=/activity/oj&qru=/ta/coding-interviews/question-ranking

    注意:

    1.要求不能创建任何新的结点,只能调整树中结点指针的指向。当转化完成以后,树中节点的左指针需要指向前驱,树中节点的右指针需要指向后继
    2.返回链表中的第一个节点的指针
    3.函数返回的TreeNode,有左右指针,其实可以看成一个双向链表的数据结构

    4.你不用输出双向链表,程序会根据你的返回值自动打印输出

    输入描述:

    二叉树的根节点

    返回值描述:

    双向链表的其中一个头节点

    代码:

    1. public class Solution {
    2. public TreeNode prev = null;
    3. public void ConvertChild(TreeNode root) {
    4. if(root == null) return;
    5. ConvertChild(root.left);
    6. //System.out.print(root.val+" ");
    7. root.left = prev;
    8. if(prev != null) {
    9. prev.right = root;
    10. }
    11. prev = root;
    12. ConvertChild(root.right);
    13. }
    14. public TreeNode Convert(TreeNode pRootOfTree) {
    15. if(pRootOfTree == null) return null;
    16. ConvertChild(pRootOfTree);
    17. TreeNode head = pRootOfTree;
    18. while(head.left != null) {
    19. head = head.left;
    20. }
    21. return head;
    22. }
    23. }

    从前序与中序遍历序列构造二叉树icon-default.png?t=M7J4https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal/ 

    1.把前序遍历的值构建  根节点;

    2.在中序遍历过程中找到  根节点的位置;

    3.分别构建root的左树和右树

    代码展示:

    1. class Solution {
    2. public int preIndex = 0;
    3. private TreeNode buildTreeChild(int[] preorder,int[] inorder,int inbegin,int inend) {
    4. //没有了左树 或者 没有了右树
    5. if(inbegin > inend) {
    6. return null;
    7. }
    8. TreeNode root = new TreeNode( preorder[preIndex]);
    9. //找到当前根节点 在中序遍历中的位置
    10. int rootIndex = findInorderIndex(inorder, preorder[preIndex],inbegin,inend);
    11. preIndex++;
    12. root.left = buildTreeChild(preorder,inorder,inbegin,rootIndex-1);
    13. root.right = buildTreeChild(preorder,inorder,rootIndex+1,inend);
    14. return root;
    15. }
    16. private int findInorderIndex(int[] inorder,int val,int inbegin,int inend) {
    17. for(int i = inbegin;i <= inend;i++) {
    18. if(inorder[i] == val) {
    19. return i;
    20. }
    21. }
    22. return -1;
    23. }
    24. public TreeNode buildTree(int[] preorder, int[] inorder) {
    25. return buildTreeChild(preorder,inorder,0,inorder.length-1);
    26. }
    27. }

    从中序与后续遍历序列构造二叉树icon-default.png?t=M7J4https://leetcode.cn/problems/construct-binary-tree-from-inorder-and-postorder-traversal/submissions/

    代码如下:

    1. class Solution {
    2. public int postIndex = 0;
    3. private TreeNode buildTreeChild(int[] postorder,int[] inorder,int inbegin,int inend) {
    4. //没有了左树 或者 没有了右树
    5. if(inbegin > inend) {
    6. return null;
    7. }
    8. TreeNode root = new TreeNode( postorder[postIndex]);
    9. //找到当前根节点 在中序遍历中的位置
    10. int rootIndex = findInorderIndex(inorder, postorder[postIndex],inbegin,inend);
    11. postIndex--;
    12. root.right = buildTreeChild(postorder,inorder,rootIndex+1,inend);
    13. root.left = buildTreeChild(postorder,inorder,inbegin,rootIndex-1);
    14. return root;
    15. }
    16. private int findInorderIndex(int[] inorder,int val,int inbegin,int inend) {
    17. for(int i = inbegin;i <= inend;i++) {
    18. if(inorder[i] == val) {
    19. return i;
    20. }
    21. }
    22. return -1;
    23. }
    24. public TreeNode buildTree(int[] inorder, int[] postorder) {
    25. postIndex = postorder.length-1;
    26. return buildTreeChild(postorder,inorder,0,inorder.length-1);
    27. }
    28. }

     根据二叉树创建字符串icon-default.png?t=M7J4https://leetcode.cn/problems/construct-string-from-binary-tree/

     

     代码:

    1. class Solution {
    2. public String tree2str(TreeNode root) {
    3. StringBuilder sb = new StringBuilder();
    4. tree2strChild(root,sb);
    5. return sb.toString();
    6. }
    7. private void tree2strChild(TreeNode root,StringBuilder sb){
    8. if(root == null) return;
    9. sb.append(root.val);
    10. if(root.left != null){
    11. sb.append("(");
    12. tree2strChild(root.left,sb);
    13. sb.append(")");
    14. }else{
    15. if(root.right == null){
    16. return;
    17. }else{
    18. sb.append("()");
    19. }
    20. }
    21. if(root.right == null){
    22. return;
    23. }else{
    24. sb.append("(");
    25. tree2strChild(root.right,sb);
    26. sb.append(")");
    27. }
    28. }
    29. }

  • 相关阅读:
    支持向量机(二)
    以交易为生是一种什么体验?
    那些你不知道的gis开发小技巧
    Redis 三种特殊的数据类型 - Geospatial地理位置 - Hyperloglog基数统计的算法 - Bitmaps位图(位存储)
    ThinkPHP和uniapp开发的CRM售后管理系统(客户、合同、工单、任务、报价、产品、库存、出纳、收费)
    学习vue3 五,传送,缓存组件以及过渡和过渡列表
    c# 字典与内存碎片化
    服装ERP软件首要的好处都有哪些?
    线程崩溃为什么不会导致 JVM 崩溃
    Python学习笔记--字符集
  • 原文地址:https://blog.csdn.net/weixin_53939785/article/details/126458709