剑指 Offer 07. 重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。
假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
示例 1:
Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
Output: [3,9,20,null,null,15,7]
示例 2:
Input: preorder = [-1], inorder = [-1]
Output: [-1]
限制:
0 <= 节点个数 <= 5000
/**
* 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* bulid(vector<int>& preorder, vector<int>& inorder, int b1, int e1, int b2, int e2){
if(b1 >= e1)return nullptr;
TreeNode *t = new TreeNode;
t->val = preorder[b1];
int i;
for(i = b2; i < e2; ++ i){
if(inorder[i] == t->val){
break;
}
}
t->left = bulid(preorder, inorder, b1 + 1, b1 + i - b2 + 1, b2, i);
t->right = bulid(preorder, inorder, b1 + i - b2 + 1, e1, i + 1, e2);
return t;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
int n = preorder.size();
if(n == 0)return nullptr;
TreeNode* root;
root = bulid(preorder, inorder, 0, n, 0, n);
return root;
}
};
算法思路
一棵二叉树前序遍历的结果一根节点为首,然后两棵子树的的前序遍历结果分别位于剩余数组的两侧;而中序遍历的结果根节点在数组中间,左右子树的中序遍历结果位于根节点左右两边。知道这个特点后,我们就可以对数组进行分治,对两段数组,一段前序一段中序,我们可以在前序中找到根节点,然后在中序中找到左右结点的个数,然后继续向子树遍历,直到数组大小变为1开始回溯。
剑指 Offer 16. 数值的整数次方
实现 pow(x, n) ,即计算 x 的 n 次幂函数(即,x^n)。不得使用库函数,同时不需要考虑大数问题。
示例 1:
输入:x = 2.00000, n = 10
输出:1024.00000
示例 2:
输入:x = 2.10000, n = 3
输出:9.26100
示例 3:
输入:x = 2.00000, n = -2
输出:0.25000
解释:2-2 = 1/22 = 1/4 = 0.25
提示:
-100.0 < x < 100.0
-231 <= n <= 231-1
-104 <= xn <= 104
class Solution {
public:
double myPow(double x, int n) {
if(n == 0){
return 1;
}else if(abs(n % 2) == 1){
if(n > 0){
return myPow(x, n - 1) * x;
}else{
return myPow(x, n + 1) / x;
}
}else{
double tmp = myPow(x, n / 2);
return tmp * tmp;
}
}
};
算法思路
这里我用的是快速幂,快速幂的大概原理就是a^2n = a^n * a^n
,就是不用乘2n
次,某些情况下可以通过自乘达到减少大量乘法的效果,有点向昨天说的倍增,达到n不一定要走n
次,logn
就可以搞定。
剑指 Offer 33. 二叉搜索树的后序遍历序列
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true
,否则返回 false
。假设输入的数组的任意两个数字都互不相同。
参考以下这颗二叉搜索树:
5
/ \
2 6
/ \
1 3
示例 1:
输入: [1,6,3,2,5]
输出: false
示例 2:
输入: [1,3,2,6,5]
输出: true
提示:
数组长度 <= 1000
class Solution {
public:
bool check(vector<int> &postorder, int beg, int end){
if(beg > end){
return true;
}
int i = beg;
while(i < end && postorder[i] < postorder[end])i ++;
for(int j = i + 1; j < end; ++ j){
if(postorder[j] < postorder[end]){
return false;
}
}
if(i == end || i == beg){
return check(postorder, beg, end - 1);
}else{
return check(postorder, beg, i - 1) && check(postorder, i, end - 1);
}
}
bool verifyPostorder(vector<int>& postorder) {
int n = postorder.size();
return check(postorder, 0, n - 1);
}
};
算法思路
这一题和第一题很像,用的是分治的思想,后序遍历序列的特点是序列最后一个元素为根,两棵子树的元素位于剩余序列的前后两个部分,又因为是二叉搜索树,所以剩余序列的前半部分小于根,后半部分大于根,因此我们可以很快地写出递归函数。不是二叉搜索树的条件是除根节点外剩余序列可以分为大于根和小于根两部分;是二叉搜索树的条件是剩余序列满足条件且两部分都能作为单独的二叉搜索树后序序列。
【剑指Offer】系列:
【剑指Offer】栈
【剑指Offer】链表
【剑指Offer】字符串
【剑指Offer】查找算法
【剑指Offer】查找算法(1)
【剑指Offer】搜索与回溯算法
【剑指Offer】搜索与回溯算法(1)
【剑指Offer】动态规划
【剑指Offer】动态规划(1)
【剑指Offer】动态规划(2)
【剑指Offer】双指针
【剑指Offer】双指针(1)
【剑指Offer】双指针(2)
【剑指Offer】搜索与回溯算法(2)
【剑指Offer】搜素与回溯算法(3)
【剑指Offer】排序
【剑指Offer】排序(1)
【剑指Offer】搜索与回溯算法(4)
【剑指Offer】搜索与回溯算法(5)