2022.5.5 剑指offer 07,16,33,15,65

这篇博客介绍了如何根据前序遍历和中序遍历重建二叉树,以及如何实现数值的快速幂运算。此外,还讲解了验证二叉搜索树后序遍历序列的方法以及计算二进制中1的个数的三种算法。最后,展示了如何用位操作进行无加减乘除的加法。
摘要由CSDN通过智能技术生成
学习剑指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;
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值