【Android春招每日一练】(十八) 剑指5题+年度总结

概览

剑指offer:不用加减乘除做加法、构建乘积数组、把字符串转换成整数、二叉搜索树的最近公共祖先、二叉树的最近公共祖先

剑指offer

1.70 不用加减乘除做加法

写一个函数,求两个整数之和,要求在函数体内不得使用 “+”、“-”、“*”、“/” 四则运算符号。

解:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OXo1cF2Y-1643595045264)(D:\Typora\img\image-20220130102907058.png)]

观察发现,无进位和 与 异或运算 规律相同,进位 和 与运算 规律相同(并需左移一位)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lW16kdGn-1643595045266)(D:\Typora\img\56d56524d8d2b1318f78e209fffe0e266f97631178f6bfd627db85fcd2503205-Picture1.png)]

//位运算
class Solution {
    public int add(int a, int b) {
        while(b != 0){					// 当进位为 0 时跳出
            int carry = (a & b) << 1;	//进位
            a ^= b;						//非进位和加
            b = carry;
        }
        return a;
    }
}
1.71 构建乘积数组

给定一个数组 A[0,1,…,n-1],请构建一个数组 B[0,1,…,n-1],其中 B[i] 的值是数组 A 中除了下标 i 以外的元素的积, 即 B[i]=A[0]×A[1]×…×A[i-1]×A[i+1]×…×A[n-1]。不能使用除法。

示例:

输入: [1,2,3,4,5]
输出: [120,60,40,30,24]
// 表格法
class Solution {
    public int[] constructArr(int[] a) {
        if(a.length == 0) return new int[0];
        int[] b = new int[a.length];
        b[0] = 1;
        int temp = 1;

        // 计算b:b[i]表示a[0...i-1]的乘积
        for(int i=1; i<a.length; i++){
            b[i] = b[i-1] * a[i-1];
        }
        // temp 表示a[i...n-1]的乘积
        for(int i=a.length-1; i>=0; i--){
            b[i] *= temp;
            temp *= a[i];
        }
        return b;
    }
}
1.72 把字符串转换成整数

写一个函数 StrToInt,实现把字符串转换成整数这个功能。不能使用 atoi 或者其他类似的库函数。

首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。

当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组合起来,作为该整数的正负号;假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。

该字符串除了有效的整数部分之后也可能会存在多余的字符,这些字符可以被忽略,它们对于函数不应该造成影响。

注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换。

在任何情况下,若函数不能进行有效的转换时,请返回 0。

说明:

假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231, 231 − 1]。如果数值超过这个范围,请返回 INT_MAX (231 − 1) 或 INT_MIN (−231) 。

class Solution {
    public int strToInt(String str) {
        //去除str首尾的多余空格
        char[] array = str.trim().toCharArray();
        //如果array的长度为0 返回0
        if (array.length==0) return 0;
        //sign表示标志位  1为正  -1 为负  i代表array从何处开始遍历
        int res = 0, sign = 1, i = 1;
        //设置限制值,因为在遍历中先判断res是否越界,再向res赋值,因而对limit的要求/10
        int limit = Integer.MAX_VALUE / 10;
        //如果array[0]=- 表明该数是负数  sign =-1
        if (array[0]=='-') sign = -1;
        else if (array[0]!='+') i = 0;
        for (int j = i; j < array.length; j++) {
            //判断当前字符是否为数字  不是直接退出
            if (array[j]>'9'||array[j]<'0') break;
            //判断遍历到j-1的位置后  res是否大于limit 如果当前res已经大于limit  加上array[j]一定越界
            //当res等于limit时,我们需要判断array[j]是否大于Integer.MAX_VALUE的末位数7
            if (res>limit||res==limit&&array[j]>'7') return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
            res = res * 10 + (array[j] - '0');
        }
        return res*sign;
    }
}
1.73 二叉搜索树的最近公共祖先

给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kz3glC4f-1643595045269)(D:\Typora\img\binarysearchtree_improved.png)]

示例 1:

输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
输出: 6 
解释: 节点 2 和节点 8 的最近公共祖先是 6。
//迭代
class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        while(root != null) {
            if(root.val < p.val && root.val < q.val) // p,q 都在 root 的右子树中
                root = root.right; // 遍历至右子节点
            else if(root.val > p.val && root.val > q.val) // p,q 都在 root 的左子树中
                root = root.left; // 遍历至左子节点
            else break;
        }
        return root;
    }
}
//递归
class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root.val < p.val && root.val < q.val)
            return lowestCommonAncestor(root.right, p, q);
        if(root.val > p.val && root.val > q.val)
            return lowestCommonAncestor(root.left, p, q);
        return root;
    }
}
1.74 二叉树的最近公共祖先

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

例如,给定如下二叉树: root = [3,5,1,6,2,0,8,null,null,7,4]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MwsMWJaM-1643595045271)(D:\Typora\img\binarytree.png)]

示例 1:

输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出: 3
解释: 节点 5 和节点 1 的最近公共祖先是节点 3。
//DFS
class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root == null || root == p || root == q) return root;
        TreeNode left = lowestCommonAncestor(root.left,p,q);
        TreeNode right = lowestCommonAncestor(root.right,p,q);
        //左右子树同时为null,root左右子树均不包含p,q,返回null
        if(left == null && right == null) return null;
        //左为空,右不为空,p,q不在左子树中,返回right,分为两种情况:
        //p,q 其中一个在root的右子树中,此时right指向p(假设为p);
		//p,q 两节点都在root的右子树中,此时的right指向最近公共祖先节点 ;
        if(left == null) return right;
        //左不为空,右为空,p,q不在右子树中,返回left
        if(right == null) return left;
        return root;	//if(left != null and right != null)
    }
}

年度总结

  • Java和Android的基础知识点基本整理完了(当然还有很多遗漏的),来年会先复习计算机基础知识,然后收集整理面经查漏补缺,再学习常见框架(源码),熟悉项目。
  • 算法已经基本刷完《剑指offer》的题,来年继续LeetCode100热题,最后进行模板总结。
  • 今天是2022年1月31日,除夕。回顾这一年,我遇到了一个真心爱我的人,遇到了许多好老师,做了一个外包的项目,参加了互联网比赛,也收获了一份较为满意的成绩…
    来年三月,我将正式进行春招,在前行中跌倒,又站起来继续前行~
    我本平凡,仅因对互联网的热爱,让我踏上这一条路,相信明年将会更好,未来可期,新年快乐~
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

leisure-ZL

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值