[算法专题] Binary Tree
1 Same Tree
https://leetcode.com/problems/same-tree/
Given two binary trees, write a function to check if they are equal or not.
Two binary trees are considered equal if they are structurally identical and the nodes have the same value.
分治的思想,如果root相等,再看左右子树是否相等。
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: bool isSameTree(TreeNode* p, TreeNode* q) { if (p == NULL && q == NULL) { return true; } if (p == NULL || q == NULL) { return false; } if (p->val != q->val) { return false; } return isSameTree(p->left, q->left) && isSameTree(p->right, q->right); } };
2 SubTree
http://www.lintcode.com/en/problem/subtree/
You have two every large binary trees:
T1
, with millions of nodes, andT2
, with hundreds of nodes. Create an algorithm to decide ifT2
is a subtree ofT1
.Example
T2 is a subtree of T1 in the following case:
1 3 / \ / T1 = 2 3 T2 = 4 / 4
T2 isn't a subtree of T1 in the following case:
1 3 / \ \ T1 = 2 3 T2 = 4 / 4
仍然是分治的思想。如果T1当前root节点与T2的root节点相同,我们才有兴趣判断T2是否是T1的子树。如果不同,判断T2是否是T1的左子树的子树或者是T1的右子树的子树。
/** * Definition of TreeNode: * class TreeNode { * public: * int val; * TreeNode *left, *right; * TreeNode(int val) { * this->val = val; * this->left = this->right = NULL; * } * } */ class Solution { public: /** * @param T1, T2: The roots of binary tree. * @return: True if T2 is a subtree of T1, or false. */ bool isSubtree(TreeNode *T1, TreeNode *T2) { if (T2 == NULL) { return true; } // //we have exhauste the root1 already if (T1 == NULL) { return false; } if (T1->val == T2->val) { if (isSameTree(T1, T2)) { return true; } } return isSubtree(T1->left, T2) || isSubtree(T1->right, T2); } private: bool isSameTree(TreeNode *T1, TreeNode *T2) { if (T1 == NULL && T2 == NULL) { return true; } if (T1 == NULL || T2 == NULL) { return false; } if (T1->val != T2->val) { return false; } return isSameTree(T1->left, T2->left) && isSameTree(T1->right, T2->right); } };
3 计算树的深度
int treeDepth(TreeNode *root) { // base case if (root == NULL) { return 0; } return max(treeDepth(root->left), treeDepth(root->right)) + 1; }
4 Path Sum
https://leetcode.com/problems/path-sum/
Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum.
For example:
Given the below binary tree andsum = 22
,5 / \ 4 8 / / \ 11 13 4 / \ \ 7 2 1return true, as there exist a root-to-leaf path
5->4->11->2
which sum is 22.
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: bool hasPathSum(TreeNode* root, int sum) { // base case if (root == NULL) { return false; } // 当前递归层是否满足条件? if (root->val == sum && root->left == NULL && root->right == NULL) { return true; } return hasPathSum(root->left, sum - root->val) || hasPathSum(root->right, sum - root->val); } };
5 Path Sum II
https://leetcode.com/problems/path-sum-ii/
Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given sum.
For example:
Given the below binary tree andsum = 22
,5 / \ 4 8 / / \ 11 13 4 / \ / \ 7 2 5 1return
[ [5,4,11,2], [5,8,4,5] ]
解法1:
dfs中的sum参数记录了当前递归层需要满足的条件
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: vector<vector<int>> pathSum(TreeNode* root, int sum) { vector<vector<int>> result; vector<int> path; dfs(root, result, path, sum); return result; } private: void dfs(TreeNode *root, vector<vector<int>> &result, vector<int> &path, int sum) { if (root == NULL) { return; } path.push_back(root->val); if (root->val == sum && root->left == NULL && root->right == NULL) { result.push_back(path); } dfs(root->left, result, path, sum - root->val); dfs(root->right, result, path, sum - root->val); path.pop_back(); } };
解法2:
考虑几个问题,dfs的对象是谁?什么时候满足push到result的条件?递归基是什么?
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: vector<vector<int>> pathSum(TreeNode* root, int sum) { vector<vector<int>> result; vector<int> path; dfs(root, result, path, sum); return result; } private: void dfs(TreeNode *root, vector<vector<int>> &result, vector<int> &path, const int &sum) { if (root == NULL) { return; } path.push_back(root->val); if (root->left == NULL && root->right == NULL) { int tmp = 0; for (vector<int>::const_iterator itr = path.cbegin(); itr != path.cend(); itr++) { tmp += *itr; } if (tmp == sum) { result.push_back(path); } } dfs(root->left, result, path, sum); dfs(root->right, result, path, sum); path.pop_back(); } };
6 Binary Tree Maximum Path Sum
https://leetcode.com/problems/binary-tree-maximum-path-sum/
Given a binary tree, find the maximum path sum.
The path may start and end at any node in the tree.
For example:
Given the below binary tree,1 / \ 2 3Return
6
.
采用分治法。要求当前tree的最大路径和,可以考虑左子树的最大路径和、右子树的最大路径和、以及包含当前结点的最大路径和三者中的最大值。
要求包含当前结点的最大路径和,需要知道左子树的单路最大路径和leftChildSingleMaxSum、右子树的单路最大路径和rightChildSingleMaxSum。其中,max( leftChildSingleMaxSum + rightChildSingleMaxSum + root->val, leftChildSingleMaxSum + root->val, rightChildSingleMaxSum + root->val),即为包含当前结点的最大路径和。
由以上分析,不难得知,遍历每一个节点时,需要得到其单路最大路径和以及双路最大路径和。我们将其封装为returnType。
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ struct returnType { returnType(int singlePath, int doublePath) :singlePath_(singlePath), doublePath_(doublePath) { } int singlePath_; int doublePath_; }; class Solution { public: int maxPathSum(TreeNode* root) { return maxPathSumHelper(root).doublePath_; } private: returnType maxPathSumHelper(TreeNode *root) { if (root == NULL) { return returnType(0, numeric_limits<int>::min()); } // devide returnType left = maxPathSumHelper(root->left); returnType right = maxPathSumHelper(root->right); // conquer int singlePath = getMax(left.singlePath_ + root->val, right.singlePath_ + root->val, root->val); int doublePath = getMax(left.doublePath_, right.doublePath_, max(left.singlePath_ + right.singlePath_ + root->val, singlePath)); return returnType(singlePath, doublePath); } int getMax(int x, int y, int z) { return (x = x > y ? x : y ) > z ? x : z; } };
7 最近公共祖先
http://www.lintcode.com/zh-cn/problem/lowest-common-ancestor/
最近公共祖先
给定一棵二叉树,找到两个节点的最近公共父节点(LCA)。
最近公共祖先是两个节点的公共的祖先节点且具有最大深度。
样例
对于下面这棵二叉树
4 / \ 3 7 / \ 5 6
LCA(3, 5) =
4
LCA(5, 6) =
7
LCA(6, 7) =
7
如果两个节点都在同一棵子树中,则继续往该子树中查找。如果两个节点在不同的子树中,那么root即为最近公共祖先。
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: TreeNode *lowestCommonAncestor(TreeNode *root, TreeNode *p, TreeNode *q) { // p,q均在左子树中 if (covers(root->left, p) && covers(root->left, q)) { return lowestCommonAncestor(root->left, q, p); } // p,q均在右子树中 if (covers(root->right, p) && covers(root->right, q)) { return lowestCommonAncestor(root->right, q, p); } // base case:p,q在不同的子树中,或者root即为p,q中的某一个节点 return root; } // 辅助函数,判断节点p是否在子树中。 bool covers(TreeNode *root, TreeNode *p) { if (root == NULL) { return false; } if (root == p) { return true; } return covers(root->left, p) || covers(root->right, p); } };
8 Convert Sorted Array to Binary Search Tree
Tree与其他数据结构转换这类题⽬目要求将树的结构转化成其他数据结构,例如linked list, array等,或者反之,从array等结构构成⼀棵树。
前者通常是通过树的遍历,合并局部解来得到全局解,而后者则可以利⽤分治的策略,递归将数据结构的两部分分别转换成子树,再合并。
https://leetcode.com/problems/convert-sorted-array-to-binary-search-tree/
Given an array where elements are sorted in ascending order, convert it to a height balanced BST.
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: TreeNode* sortedArrayToBST(vector<int>& nums) { return sortedArrayToBstHelper(nums, 0, nums.size() - 1); } private: TreeNode* sortedArrayToBstHelper(const vector<int> &nums, int start, int end) { if (start > end) { return NULL; } if (start == end) { return new TreeNode(nums[start]); } int mid = start + ((end - start) >> 1); TreeNode *l = sortedArrayToBstHelper(nums, start, mid - 1); TreeNode *r = sortedArrayToBstHelper(nums, mid + 1, end); TreeNode *root = new TreeNode(nums[mid]); root->left = l; root->right = r; return root; } };
9