学习剑指offer 20、21天
07 重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。
假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
return subBuildTree(preorder, 0, preorder.length, inorder, 0 , inorder.length);
}
public TreeNode subBuildTree(int[] preorder, int pre_left, int pre_right, int[] inorder, int in_left, int in_right){
if(in_right - in_left <= 0) return null;
TreeNode node = new TreeNode();
// 前序遍历中第一个数为根节点
int target = preorder[pre_left];
node.val = target;
if(in_right - in_left == 1){
return node;
}
// 从当前区间找target
int index = in_left;
// 在中序遍历中找到值为根节点的索引
for(; index < in_right; index++){
if(inorder[index] == target) break;
}
// 注意左右边界
node.left = subBuildTree(preorder, pre_left + 1, pre_left + (index - in_left) + 1, inorder, in_left, index);
node.right = subBuildTree(preorder, pre_left + (index - in_left) + 1, pre_right, inorder, index + 1, in_right);
return node;
}
}
16 数值的整数次方
public double myPow(double x, int n) {
// 需要同时考虑n的奇偶与正负,并且需要考虑临界值
if(x == 0) return 0;
if(n == 0) return 1;
if(n == 1) return x;
if(n == -1) return 1/x;
double res = myPow(x, n / 2);
// 考虑奇偶和正负
if(n % 2 != 0){
if(n > 0) return res * res * x;
if(n < 0) return res * res * (1 / x);
}
return res * res;
}
33 二叉搜索树的后序遍历序列
该题利用二叉搜索树和后序遍历的两个性质
public boolean verifyPostorder(int[] postorder) {
return subverifyPostorder(postorder, 0, postorder.length - 1);
}
//左闭右闭
public boolean subverifyPostorder(int[] postorder, int left, int right){
// 终止条件
if(right - left < 1) return true;
// 后序遍历中,最后一个为根节点的值,所以遍历数组,找到小于taget的那部分,在找到大于taget的那部分,判断这两部分中是否有不满足要求的节点,如果有则证明不是二叉搜索树的后序遍历
int taget = postorder[right];
// 找到小于taget和大于taget的第一个分界点
int index = left;
for(; index < right; index++){
if(postorder[index] > taget) break;
}
int dil = index;
//判断是否为第二个分界点,如果有则不是
for(; index < right; index++){
if(postorder[index] < taget) return false;
}
// 判断左子树和右子树
return subverifyPostorder(postorder, left, dil - 1) && subverifyPostorder(postorder, dil, right - 1);
}
}
15 二进制中1的个数
- 法一:
使用Integer.toBinaryString()方法,可以计算出n中1的个数
public int hammingWeight(int n) {
//java中各个位为1的数为-1,首先将n与-1二位与
String result = Integer.toBinaryString(n);
int count = 0;
for(char c : result.toCharArray()){
if(c == '1') count++;
}
return count;
}
- 法二
每次都判断最后一位,判断的方法是和1进行与操作。
public int hammingWeight(int n) {
int count = 0;
while(n != 0){
count += n & 1;
//无符号右移
n = n >>> 1;
}
return count;
}
- 法三
使用n & (n - 1):该操作可以使得n的最后一位1变成0,其余的不改变
这样可以只判断为1的位置。
public int hammingWeight(int n) {
int count = 0;
while(n != 0){
count++;
n = n & (n - 1);
}
return count;
}
65 不用加减乘除做加法
无进位和与异或运算规律相同,而进位和与与运算(+左移一位)相同。
和=非进位和n+进位c,循环求n,c,直至进位c = 0
public int add(int a, int b) {
while(b != 0){
int c = (a & b) << 1;
a = a ^ b;
b = c;
}
return a;
}