[LeetCode]Construct Binary Tree from Preorder and Inorder Traversal

本文介绍了如何利用前序和中序、后序和中序遍历序列来构建二叉树的方法。包括递归和非递归两种实现方式,并提供了详细的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

105. Construct Binary Tree from Preorder and Inorder Traversal

Given preorder and inorder traversal of a tree, construct the binary tree.

Note:
You may assume that duplicates do not exist in the tree.

题意;给定前序和中序遍历的序列,构造该二叉树

思路:

前序遍历的序列中每个元素都是一颗子树的根节点,从根节点开始到它的左子树的根节点...

而中序遍历的序列是被根节点分成了前后两部分,前面一半是左子树,后面一半是右子树;

因此,可以以前序序列中的元素为中心来划分中序序列。

例如:

前序遍历:1->2->4->5->3->6->8->7

前序序列中1时整棵树的树根,2是1的左子树的树根,4是2的左子树的树根,5是2的右子树的树根,3是1的右子树的树根......

中序遍历:4->2->5->1->8->6->3->7

中序序列中树根1将其分成{4,2,5}和{8,6,3,7},{4,2,5}正是1的左子树中的节点,{8,6,3,7}正是1的右子树中的节点;

同样2将{4,2,5}分成两部分,正好对应它的左右子树的节点,因此,可以将两个序列结合起来确定二叉树的结构。

 

递归的做法

prePos表示当前元素在前序序列中的位置下标;border是中序序列中的一个范围下标,它是当前子树在中序序列中的范围。

prePos = 1,即指向元素2时,border = [0,2],即包含[4,2,5]三个元素;

prePos = 5,即指向元素6时,border = [4,5],即包含[8,6]两个元素。

TreeNode* recursiveBuildTree(vector<int>& preorder, vector<int>& inorder, int& prePos, pair<int, int> border){
    //空的情况
    if (!inorder.size())return NULL;
    //避免无左右子树,导致下届比上届还大
    if (border.first > border.second)return NULL;
    if (border.first == border.second){//只剩唯一元素
        TreeNode *root = new TreeNode(inorder.at(border.first));
        return root;
    }
    //生成当前根节点
    TreeNode *root = new TreeNode(preorder.at(prePos));
    int middle = border.first;
    //找到当前根节点在中序遍历中的位置,将它以根节点为界分为左右子树
    while (middle <= border.second && preorder.at(prePos) != inorder.at(middle)){
        middle++;
    }
    pair<int, int>cborder(border.first,middle - 1);//左子树的范围
    root->left = recursiveBuildTree(preorder, inorder, ++prePos, cborder);//寻找左子树
    if (root->left == NULL)prePos--;//若左子树为空,则prePos不应该加一
    cborder.first = middle + 1;
    cborder.second = border.second;
    root->right = recursiveBuildTree(preorder, inorder, ++prePos, cborder);//寻找右子树
    if (root->right == NULL)prePos--;//右子树为空时,prePos不应该加一
    return root;
}

非递归的解法

TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
    //空树的情况
    if (!inorder.size())return NULL;
    TreeNode* root = new TreeNode(preorder.at(0));
    stack<pair<TreeNode*,pair<int,int>>>s;
    int prei = 0;//当前访问的元素在前序序列中的位置
    pair<int, int>border(0,inorder.size() - 1);//当前元素对应在中序序列中的范围
    pair<TreeNode*, pair<int, int>> e0(root,border);
    s.push(e0);
    while (!s.empty()){
        pair<TreeNode*, pair<int, int>> p = s.top();
        int middle = p.second.first;
        //找到当前根节点在中序遍历中的位置,将它以根节点为界分为左右子树
        while (middle <= p.second.second && p.first->val != inorder.at(middle)){
            middle++;
        }
        //没有找到,序列有错,无法得到二叉树
        if (middle > p.second.second)return NULL;
        //左子树为空或为叶节点,或左子树已访问过
        if (middle - 1 <= p.second.first || p.first->left != NULL){
            if (p.first->left == NULL && middle - 1 == p.second.first){//左子树是叶节点
                ++prei;
                TreeNode* left = new TreeNode(inorder.at(middle - 1));
                p.first->left = left;
            }
            s.pop();
            if (middle + 1 == p.second.second){//右子树是叶节点
                ++prei;
                TreeNode* right = new TreeNode(inorder.at(middle + 1));
                p.first->right = right;
            }
            else if (middle + 1 < p.second.second){//进入右子树
                ++prei;
                pair<int, int>rightBorder(middle + 1, p.second.second);
                TreeNode* right = new TreeNode(preorder.at(prei));
                p.first->right = right;
                pair<TreeNode*, pair<int, int>> rightNode(right, rightBorder);
                s.push(rightNode);
            }
        }else{//进入左子树
            ++prei;
            pair<int, int>leftBorder(p.second.first,middle - 1);
            TreeNode* left = new TreeNode(preorder.at(prei));
            p.first->left = left;
            pair<TreeNode*, pair<int, int>> leftNode(left,leftBorder);
            s.push(leftNode);
        }
    }
    return root;
}

 

106 Construct Binary Tree from Inorder and Postorder Traversal

Given inorder and postorder traversal of a tree, construct the binary tree.

Note:
You may assume that duplicates do not exist in the tree.

题意:给定中序和后序遍历的序列,构造该二叉树

和上面的类似,后序序列是左子树、右子树、树根的顺序遍历,因此,树根必然是最后的一个元素,接着从后往前是右子树、左子树...

因此和前序相反,再结合中序就能确定树的结构。

例如:(还是上面的二叉树)

中序遍历:4->2->5->1->8->6->3->7

后序遍历:4->5->2->8->6->7->3->1

后序序列中最后的一定是树根节点1,然后3是1的右子树的树根,7是3的右子树的树根,6是3的左子树树根,8是6的儿子节点,这个是左孩子还是右孩子要根据中序的序列来确认;

例如如果中序中8在6的前面,则8是6的左孩子;反之则是6的右孩子。

因此,同理能够通过中序和后序序列的到二叉树的结构。

 

递归的做法

TreeNode* recursiveBuildTree(vector<int>& inorder, vector<int>& postorder, int& postPos, pair<int, int> border){
    //空的情况
    if (!inorder.size())return NULL;
    //避免无左右子树,导致下界比上界还大
    if (border.first > border.second)return NULL;
    if (border.first == border.second){//只剩唯一元素
        TreeNode *root = new TreeNode(inorder.at(border.first));
        return root;
    }
    //生成当前根节点
    TreeNode *root = new TreeNode(postorder.at(postPos));
    int middle = border.first;
    //找到当前根节点在中序遍历中的位置,将它以根节点为界分为左右子树
    while (middle <= border.second && postorder.at(postPos) != inorder.at(middle)){
        middle++;
    }
    pair<int, int>cborder(middle + 1, border.second);//右子树的范围
    root->right = recursiveBuildTree(inorder, postorder, --postPos, cborder);//寻找右子树
    if (root->right == NULL)postPos++;//若右子树为空,则postPos不应该减一
    cborder.first = border.first;
    cborder.second = middle - 1;
    root->left = recursiveBuildTree(inorder, postorder, --postPos, cborder);//寻找左子树
    if (root->left == NULL)postPos++;//左子树为空时,postPos不应该减一
    return root;
}

非递归的做法

TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder){
    //空树的情况
    if (!inorder.size())return NULL;
    int prei = postorder.size() - 1;//当前访问的元素在后序序列中的位置
    TreeNode* root = new TreeNode(postorder.at(prei));
    stack<pair<TreeNode*, pair<int, int>>>s;
    pair<int, int>border(0, inorder.size() - 1);//当前元素对应在中序序列中的范围
    pair<TreeNode*, pair<int, int>> e0(root, border);
    s.push(e0);
    while (!s.empty()){
        pair<TreeNode*, pair<int, int>> p = s.top();
        int middle = p.second.first;
        //找到当前根节点在中序遍历中的位置,将它以根节点为界分为左右子树
        while (middle <= p.second.second && p.first->val != inorder.at(middle)){
            middle++;
        }
        //没有找到,序列有错,无法得到二叉树
        if (middle > p.second.second)return NULL;
        //右子树为空或为叶节点,或右子树已访问过
        if (middle + 1 >= p.second.second || p.first->right != NULL){
            if (p.first->right == NULL && middle + 1 == p.second.second){//右子树是叶节点
                --prei;
                TreeNode* right = new TreeNode(inorder.at(middle + 1));
                p.first->right = right;
            }
            s.pop();
            if (middle - 1 == p.second.first){//左子树是叶节点
                --prei;
                TreeNode* left = new TreeNode(inorder.at(middle - 1));
                p.first->left = left;
            }
            else if (middle - 1 > p.second.first){//进入左子树
                --prei;
                pair<int, int>leftBorder(p.second.first, middle - 1);
                TreeNode* left = new TreeNode(postorder.at(prei));
                p.first->left = left;
                pair<TreeNode*, pair<int, int>> leftNode(left, leftBorder);
                s.push(leftNode);
            }
        }
        else{//进入右子树
            --prei;
            pair<int, int>rightBorder(middle + 1, p.second.second);
            TreeNode* right = new TreeNode(postorder.at(prei));
            p.first->right = right;
            pair<TreeNode*, pair<int, int>> rightNode(right, rightBorder);
            s.push(rightNode);
        }
    }
    return root;
}

 

转载于:https://www.cnblogs.com/yeqluofwupheng/p/7429781.html

1. Two Sum 2. Add Two Numbers 3. Longest Substring Without Repeating Characters 4. Median of Two Sorted Arrays 5. Longest Palindromic Substring 6. ZigZag Conversion 7. Reverse Integer 8. String to Integer (atoi) 9. Palindrome Number 10. Regular Expression Matching 11. Container With Most Water 12. Integer to Roman 13. Roman to Integer 14. Longest Common Prefix 15. 3Sum 16. 3Sum Closest 17. Letter Combinations of a Phone Number 18. 4Sum 19. Remove Nth Node From End of List 20. Valid Parentheses 21. Merge Two Sorted Lists 22. Generate Parentheses 23. Swap Nodes in Pairs 24. Reverse Nodes in k-Group 25. Remove Duplicates from Sorted Array 26. Remove Element 27. Implement strStr() 28. Divide Two Integers 29. Substring with Concatenation of All Words 30. Next Permutation 31. Longest Valid Parentheses 32. Search in Rotated Sorted Array 33. Search for a Range 34. Find First and Last Position of Element in Sorted Array 35. Valid Sudoku 36. Sudoku Solver 37. Count and Say 38. Combination Sum 39. Combination Sum II 40. First Missing Positive 41. Trapping Rain Water 42. Jump Game 43. Merge Intervals 44. Insert Interval 45. Unique Paths 46. Minimum Path Sum 47. Climbing Stairs 48. Permutations 49. Permutations II 50. Rotate Image 51. Group Anagrams 52. Pow(x, n) 53. Maximum Subarray 54. Spiral Matrix 55. Jump Game II 56. Merge k Sorted Lists 57. Insertion Sort List 58. Sort List 59. Largest Rectangle in Histogram 60. Valid Number 61. Word Search 62. Minimum Window Substring 63. Unique Binary Search Trees 64. Unique Binary Search Trees II 65. Interleaving String 66. Maximum Product Subarray 67. Binary Tree Inorder Traversal 68. Binary Tree Preorder Traversal 69. Binary Tree Postorder Traversal 70. Flatten Binary Tree to Linked List 71. Construct Binary Tree from Preorder and Inorder Traversal 72. Construct Binary Tree from Inorder and Postorder Traversal 73. Binary Tree Level Order Traversal 74. Binary Tree Zigzag Level Order Traversal 75. Convert Sorted Array to Binary Search Tree 76. Convert Sorted List to Binary Search Tree 77. Recover Binary Search Tree 78. Sum Root to Leaf Numbers 79. Path Sum 80. Path Sum II 81. Binary Tree Maximum Path Sum 82. Populating Next Right Pointers in Each Node 83. Populating Next Right Pointers in Each Node II 84. Reverse Linked List 85. Reverse Linked List II 86. Partition List 87. Rotate List 88. Remove Duplicates from Sorted List 89. Remove Duplicates from Sorted List II 90. Intersection of Two Linked Lists 91. Linked List Cycle 92. Linked List Cycle II 93. Reorder List 94. Binary Tree Upside Down 95. Binary Tree Right Side View 96. Palindrome Linked List 97. Convert Binary Search Tree to Sorted Doubly Linked List 98. Lowest Common Ancestor of a Binary Tree 99. Lowest Common Ancestor of a Binary Search Tree 100. Binary Tree Level Order Traversal II
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值