day20
1.剑指 Offer 07. 重建二叉树
i.根据先序遍历(根节点 + 左子树 + 右子树)和 中序遍历(左子树 + 根节点 + 右子树)求出二叉树的思路就不写了(先序、中序、后序说的是根节点的位置顺序)
ii.dfs(preroot,inleft,inright):
preroot:先序遍历时的根节点索引(用来找到中序遍历的根节点索引 inroot = dic[preorder[preroot]],preorder[preroot]:根节点的值)
inleft:中序遍历时最左边位索引
inright:中序遍历时最右边索引
这样就知道了中序遍历时左子树和右子树的范围了:
左子树:(inleft,inroot - 1) 右子树:(inroot + 1,inright)
要进行左右子树的递归还要知道左右子树先序遍历根节点的索引:
先序遍历:根节点 + 左子树 + 右子树
左子树:preroot + 1(先序遍历根节点后一个节点就是左子树根节点)
右子树:preroot + (inroot - inleft) + 1(inroot - inleft:中序遍历时左子树节点个数,这样就求出了先序遍历左子树数目,因为二者数目是一样的;先序遍历右子树根节点 = 根节点 + 左子树节点个数 + 1)
iii.这个递归,实质上是在不断的划分根节点、左子树和右子树,划分成很多个小的二叉树,最后回溯汇总成最终要求的二叉树,体现了分治的算法思想
1 /** 2 * Definition for a binary tree node. 3 * struct TreeNode { 4 * int val; 5 * TreeNode *left; 6 * TreeNode *right; 7 * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 8 * }; 9 */ 10 class Solution { 11 public: 12 TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) { 13 this -> preorder = preorder; //成员变量与形参重名了,所以用到了this 14 int n = inorder.size(); 15 for(int i = 0;i < n;i ++) 16 dic[inorder[i]] = i; 17 return dfs(0,0,n - 1); 18 } 19 20 private: 21 vector<int> preorder; 22 unordered_map<int,int> dic; 23 TreeNode* dfs(int preroot,int inleft,int inright){ 24 if(inleft > inright) return nullptr; 25 TreeNode* root = new TreeNode(preorder[preroot]); 26 int inroot = dic[preorder[preroot]]; 27 root -> left = dfs(preroot + 1,inleft,inroot - 1); 28 root -> right = dfs(preroot + (inroot - inleft) + 1,inroot + 1,inright); 29 return root; 30 } 31 };
2.剑指 Offer 16. 数值的整数次方
快速幂解法:利用二进制,举个栗子🌰:求311,11二进制表示为1011(1 -- 23,0 -- 22,1 -- 21,1 -- 20),11 = 8(23) + 2(21) + 1(20)
1011:n & 1 == 1,x = 3
0101:n & 1 == 1,x = 32
0010:n & 1 == 0,x = 34(无用,舍去)
0001:n & 1 == 1,x = 38
0000:退出循环 ==> 311 = 3 * 32 * 38
1 class Solution { 2 public: 3 double myPow(double x, int n) { 4 if(x == 0) return 0.0; 5 double res = 1.0; 6 if(n < 0){ 7 n = -n; // n < 0,要把n变为正数,正负数二进制码不同 8 x = 1 / x; //变倒数 9 } 10 while(n){ 11 if(n & 1 == 1) // & 同位与,n和1同位与等于1 说明n二进制最低位为1 12 res *= x; 13 x *= x; 14 n = n >> 1; //用完即右移出去 15 } 16 return res; 17 } 18 };
上面那个通不过,因为int32 变量区间n∈[−2147483648,2147483647] ,所以当 n = -2147483648n=−2147483648 时执行 n = -n会因越界而赋值出错。解决方法是先将 n 存入 long 变量 b,后面用 b操作即可
1 class Solution { 2 public: 3 double myPow(double x, int n) { 4 if(x == 0) return 0.0; 5 double res = 1.0; 6 long b = n; 7 if(b < 0){ 8 b = -b; 9 x = 1 / x; 10 } 11 while(b){ 12 if(b & 1 == 1) 13 res *= x; 14 x *= x; 15 b = b >> 1; 16 } 17 return res; 18 } 19 };
3.剑指 Offer 33. 二叉搜索树的后序遍历序列
后序遍历:左子树 + 右子树 + 根节点
二叉搜索树:左子树 < 根节点,右子树 > 根节点
采用分治算法,将二叉树划分成一个个小二叉树,若每个都满足二叉搜索树的条件,最后汇总的总二叉树即为二叉搜索树,得证
1 class Solution { 2 public: 3 bool verifyPostorder(vector<int>& postorder) { 4 return dfs(postorder,0,postorder.size() - 1); 5 } 6 7 private: 8 bool dfs(vector<int>& postorder,int l,int r){ 9 if(l >= r) return true; 10 int i = l; 11 while(postorder[i] < postorder[r]) i ++; //找到左子树部分,左子树 < 根节点 12 int j = i; 13 while(postorder[j] > postorder[r]) j ++; //找到右节点部分,右子树 > 根节点 14 if(j < r) return false; 15 return dfs(postorder,l,i - 1)/* 左子树 */ && dfs(postorder,i,r - 1)/* 右子树(去除最后根节点) */; 16 } 17 };

浙公网安备 33010602011771号