二叉树笔记
1 普通二叉树
递归,每到一个新的节点就进行相应的处理。
-
每到一个新的节点,交换它的左右孩子的指向,之后继续递归。
class Solution { public: void traversal(TreeNode *root) { if (root != NULL) { TreeNode *temp = root->right; root->right = root->left; root->left = temp; traversal(root->left); traversal(root->right); } } TreeNode* mirrorTree(TreeNode* root) { traversal(root); return root; } };
-
求最大深度
class Solution { public: int max; void traversal(TreeNode *root, int depth) { if (root != NULL) { if (max < depth) { max = depth; } traversal(root->left, depth + 1); traversal(root->right, depth + 1); } } int maxDepth(TreeNode* root) { traversal(root, 1); return max; } };
-
每递归到一个节点,如果 root1 或 root2 存在,就先创建新节点 root3。
之后根据每个节点的情况,给 root3->val 赋值,并对其左孩子和右孩子进行递归。
class Solution { public: TreeNode *traversal(TreeNode *root1, TreeNode *root2) { if (root1 == nullptr && root2 == nullptr) { return nullptr; } TreeNode *root3 = new TreeNode(); if (root1 == nullptr) { root3->val = root2->val; root3->left = traversal(nullptr, root2->left); root3->right = traversal(nullptr, root2->right); } else if (root2 == nullptr) { root3->val = root1->val; root3->left = traversal(root1->left, nullptr); root3->right = traversal(root1->right, nullptr); } else { root3->val = root1->val + root2->val; root3->left = traversal(root1->left, root2->left); root3->right = traversal(root1->right, root2->right); } return root3; } TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) { TreeNode *root3 = traversal(root1, root2); return root3; } };
-
利用有序的数组构建最小高度树。二分,递归。
class Solution { public: TreeNode *buildTree(vector<int> &ans, int low, int high) { if (low > high) { return NULL; } int mid = (low + high) / 2; TreeNode *node = new TreeNode(ans[mid]); node->left = buildTree(ans, low, mid - 1); node->right = buildTree(ans, mid + 1, high); return node; } TreeNode* sortedArrayToBST(vector<int>& nums) { TreeNode *root = buildTree(nums, 0, nums.size() - 1); return root; } };
-
如果不是叶子结点,继续递归;否则将结果放到 leaves 中。
class Solution { public: void traversal(TreeNode *root, string pos, vector<string> &leaves) { if (root != nullptr) { string temp = pos + to_string(root->val); if (root->left != nullptr || root->right != nullptr) { traversal(root->left, temp, leaves); traversal(root->right, temp, leaves); } else { leaves.push_back(temp); } } } int binaryToStr(string b) { int ans = 0; for (int i = b.length() - 1; i >= 0; i--) { if (b[i] == '1') { ans += pow(2, b.length() - i - 1); } } return ans; } int sumRootToLeaf(TreeNode* root) { vector<string> l; traversal(root, "", l); int ans = 0; for (string str : l) { ans += binaryToStr(str); } return ans; } };
2 二叉搜索树
-
特点:当前节点的值比左子树大,比右子树小。
-
二叉搜索树的中序遍历序列是一个升序序列。
通过中序遍历,用 inOrder 数组来保存中序结果的序列。
前一题要求返回数值,后一题要求返回节点。
// 剑指 Offer 54. 二叉搜索树的第k大节点 class Solution { public: void traversal(TreeNode *root, vector<int> &inOrder) { if (root != NULL) { traversal(root->left, inOrder); inOrder.push_back(root->val); traversal(root->right, inOrder); } } int kthLargest(TreeNode* root, int k) { vector<int> inOrder; traversal(root, inOrder); return inOrder[inOrder.size() - k]; } };
// 700. 二叉搜索树中的搜索 class Solution { public: TreeNode *search(TreeNode *root, int val) { if (root != nullptr) { if (root->val > val) { return search(root->left, val); } else if (root->val < val) { return search(root->right, val); } else { // root->val == val return root; } } return nullptr; } TreeNode* searchBST(TreeNode* root, int val) { TreeNode *res = search(root, val); return res; } };
-
在前面两题的基础上,再使用双指针来求解有序数组中的两数之和问题。
class Solution { public: void traversal(TreeNode *root, vector<int> &inOrder) { if (root != nullptr) { traversal(root->left, inOrder); inOrder.push_back(root->val); traversal(root->right, inOrder); } } bool findTarget(TreeNode* root, int k) { vector<int> inOrder; traversal(root, inOrder); int size = inOrder.size(); int left = 0, right = size - 1; while (left < right) { if (inOrder[left] + inOrder[right] == k) { return true; } else if (inOrder[left] + inOrder[right] > k) { // 由于序列是升序列,当前和过大,应减小右侧指针 right--; } else { // 当前和过小,左指针++ left++; } } return false; } };
-
序列已经给定,使用二分法建树。
class Solution { public: TreeNode *traversal(vector<int> &nums, int low, int high) { if (low <= high) { int mid = (low + high) / 2; TreeNode *node = new TreeNode(nums[mid]); node->left = traversal(nums, low, mid - 1); node->right = traversal(nums, mid + 1, high); return node; } return nullptr; } TreeNode* sortedArrayToBST(vector<int>& nums) { TreeNode *root = traversal(nums, 0, nums.size() - 1); return root; } };
-
每遍历到一个节点,判断它的值是否在规定的范围([low, high])内,
如果是,则范围递归左右子树节点之和;
如果 < low,则对当前节点的右子树进行递归;
如果 > high,则对当前节点的左子树进行递归。class Solution { public: int rangeSumBST(TreeNode* root, int low, int high) { if (root == nullptr) { return 0; } if (root->val >= low && root->val <= high) { return root->val + rangeSumBST(root->left, low, high) + rangeSumBST(root->right, low, high); } else if (root->val > high) { return rangeSumBST(root->left, low, high); } else { // root->val < low return rangeSumBST(root->right, low, high); } } };
-
按照题意,先递归形成中序遍历序列的队列;
然后根据生成的队列进行处理:
- 设置 temp 保存当前队列首部的节点指针;
- 将每一个节点的 left 设为 nullptr;
- 如果取出 temp 后,队列为空(temp 可能是最后一个需要处理的节点指针),就将 right 设为 nullptr;否则就设为 队列首部的节点指针。
class Solution { public: void process(TreeNode *root, queue<TreeNode*> &q) { if (root != nullptr) { process(root->left, q); q.push(root); process(root->right, q); } } TreeNode* increasingBST(TreeNode* root) { queue<TreeNode*> q; process(root, q); TreeNode *head = q.front(); while (!q.empty()) { TreeNode *temp = q.front(); q.pop(); temp->left = nullptr; if (!q.empty()) { temp->right = q.front(); } else { temp->right = nullptr; } } return head; } };
3 N 叉树(普通树)
-
N 叉树的每一个节点的子节点数目不确定。
-
N 叉树的遍历
N 叉树的前序遍历对应于二叉树的前序遍历:先根节点,后子节点。
后序遍历对应于二叉树的后序遍历:先子节点,后根节点。
-
题目链接:
-
前序遍历
class Solution { public: void postOrderTraversal(Node *root, vector<int> &ans) { if (root != nullptr) { int size = root->children.size(); for (int i = 0; i < size; i++) { postOrderTraversal(root->children[i], ans); } ans.push_back(root->val); } } vector<int> postorder(Node* root) { vector<int> ans; postOrderTraversal(root, ans); return ans; } };
后序遍历
class Solution { public: void postOrderTraversal(Node *root, vector<int> &ans) { if (root != nullptr) { int size = root->children.size(); for (int i = 0; i < size; i++) { postOrderTraversal(root->children[i], ans); } ans.push_back(root->val); } } vector<int> postorder(Node* root) { vector<int> ans; postOrderTraversal(root, ans); return ans; } };
-
-
求最大深度
和求二叉树的最大深度差不多。
-
题目链接
class Solution { public: void traversal(Node *root, int depth, int &max) { if (root != nullptr) { int size = root->children.size(); if (depth > max) { max = depth; } for (int i = 0; i < size; i++) { traversal(root->children[i], depth + 1, max); } } } int maxDepth(Node* root) { int max = 0; traversal(root, 1, max); return max; } };
-