1. 重建二叉树
给出二叉树的前序遍历和中序遍历,重建二叉树。树是通过递归定义的,所以这题重建也是使用递归去重建。
先顺序遍历的首元素就是二叉树的根节点。再去中序遍历中去找这个元素,即可分出左子树和右子树。遍历先序遍历,1.树的根节点、2.左子树根节点、3.右子树根节点。对于树的左、右子树,仍可使用以上步骤划分子树的左右子树。
因为中序遍历和前序遍历元素个数肯定一致,所以可以通过中序遍历去确定前序遍历中左子树和右子树的分界线。
class Solution {private:unordered_map<int, int> index;public:TreeNode *myBuildTree(const vector<int> &preorder, const vector<int> &inorder, int preorder_left, int preorder_right,int inorder_left, int inorder_right) {if (preorder_left > preorder_right) {return nullptr;}int preorder_root = preorder_left;int inorder_root = index[preorder[preorder_root]];TreeNode *root = new TreeNode(preorder[preorder_root]);int size_left_subtree = inorder_root - inorder_left;root->left = myBuildTree(preorder, inorder, preorder_left + 1, preorder_left + size_left_subtree, inorder_left,inorder_root - 1);root->right = myBuildTree(preorder, inorder, preorder_left + size_left_subtree + 1, preorder_right,inorder_root + 1, inorder_right);return root;}TreeNode *buildTree(vector<int> &preorder, vector<int> &inorder) {int n = preorder.size();for (int i = 0; i < n; ++i) {index[inorder[i]] = i;}return myBuildTree(preorder, inorder, 0, n - 1, 0, n - 1);}};//前序遍历 preorder = [3,9,20,15,7]//中序遍历 inorder = [9,3,15,20,7]
2. 数值的整数次方
暴力法用for坐下来时间复杂度有n,分治法可以降为log2n,思路也很简单,递归和分治,比如。奇数只需要用取余%2即可。
class Solution {public:double myPow(double x, int n) {if (n == 0)return 1;if (n == 1)return x;if (n == -1)return 1 / x;double half = myPow(x, n / 2);double rest = myPow(x, n % 2);return rest * half * half;}};
3. 二叉搜索树的后序遍历序列
递归+分治。利用二叉搜索树的性质,设置一个pointer遍历vector,找到左子树和右子树的划分点,递归下去继续。
class Solution{public:bool verifyPostorder(vector<int>& postorder){return recur(postorder, 0, postorder.size() - 1);}private:bool recur(vector<int> &postorder, int i,int j){//设置递归结束条件if (i>=j)return true;int point = i;//遍历while (postorder[point]<postorder[j])point++;int m = point;while (postorder[point]>postorder[j])point++;return point==j && recur(postorder,i,m-1) && recur(postorder,m,j-1);}};
