我在2016年8月3日下午3点半~6点半进行了三轮面试,除了自己做过的项目,也问了一些通用的问题。
当时本人能回答的包括:
AsyncTask和Handler+Thread机制的区别;
哈希表原理
红黑树(由Java 8中HashMap的新特性引申)
Int类型整数二进制1的个数(算法题,手写)
楼梯走法次数(算法题,手写)
……
当时不会的包括:
Java中final修饰成员函数的作用
Java中线程池如何设计的(由AsyncTask引申出来的题目,参见“Java线程池原理与实例详解”)
自定义控件如何设计,例如显示gif图片
……
##一面算法题
题目:Int类型整数二进制1的个数,例如3的二进制是11,1的个数是2。
【分析】
方法一:判断最后一位是否是1,然后不断右移该整数,继续判断,直到该数为0。这个算法对于正数有效,但是对于负数无效。因为右移时最左侧会补符号位,正数就是补0,而负数就是补1。不过,由于java中有右移补0的符号>>>,所以,该算法可行。
public static int bitCounter2( int n){
int c =0 ; // 计数器
while (n !=0)
{
if((n &1) ==1) // 当前位是1
++c ; // 计数器加1
n >>>=1 ; // 移位,左侧补0,n改变了!
}
return c ;
}
方法二:向左移动掩码1,然后进行位运算“&”,就能判断该位是否是1。本方法还能保证被判断数不变。
public static int bitCounter(int n){
int mask=1;
int counter=0;
while ((n&mask)!=0) {
counter++;
mask<<=1;
}
return counter++;
}
这是我面试的回答,当然,回来一查,“算法-求二进制数中1的个数”中有更多好的方法。
##二面算法题
题目:一个人迈步上台阶,一次可以迈1阶、2阶、3阶,这样,到1阶的走法有1中,到2阶的走法有2中,到3阶的走法有4种,那么到第n级的走法有多少种?
【分析】走到n阶前,可能位于n-1阶,再迈1步1阶即可;可能为n-2阶,再迈1步2阶即可;可能位于n-3阶,再迈1步3阶即可。递归公式:f(n)= f(n-1)+ f(n-1)+ f(n-2)。
解法一:递归
public static int stepCounter(int n){
if (n<=0) throw new IllegalArgumentException("参数错误,n必须大于0!");
if (n==1) return 1;
if (n==2) return 2;
if (n==3) return 4;
return stepCounter(n-1)+stepCounter(n-2)+stepCounter(n-3);
}
解法二:空间换时间(类似动态规划)
public static int stepCounter2(int n){
if (n<=0) throw new IllegalArgumentException("参数错误,n必须大于0!");
int[] counter=new int[n+1];
counter[1]=1;
counter[2]=2;
counter[3]=4;
for (int i = 4; i < n+1; i++) {
counter[i]=counter[i-1]+counter[i-2]+counter[i-3];
}
return counter[n];
}
然后面试官问我是否可以优化,我说空间可以再小一点,只记录最近的3次。
public static int stepCounter2(int n){
if (n<=0) throw new IllegalArgumentException("参数错误,n必须大于0!");
int[] counter=new int[4];
counter[1]=1;
counter[2]=2;
counter[3]=4;
for (int i = 4; i < n+1; i++) {
//counter[0]用来存储结果
counter[0]=counter[1]+counter[2]+counter[3];
//移动前三个数
counter[1]=counter[2];
counter[2]=counter[3];
counter[3]=counter[0];
}
return counter[3];
}
写这篇博客时我想,其实最后三个数的交换也是没有必要的,只要记住返回值的位置就OK。
public static int stepCounter3(int n){
if (n<=0) throw new IllegalArgumentException("参数错误,n必须大于0!");
int[] counter=new int[4];
int j=0;//返回值的位置
for (int i = 1; i < n+1; i++) {
j=i%4;
if (i==1) {
counter[j]=1;
}else if (i==2) {
counter[j]=2;
}else if (i==3) {
counter[j]=4;
}else {
counter[j]=0;//清0
for (int k = 0; k < 4; k++) {
if (k==j) continue;
counter[j]+=counter[k];//其它三个数之和
}
}
}
return counter[j];
}
请我喝咖啡
如果觉得写得不错,可以扫描我的微信二维码请我喝咖啡哦~
或者点击 打赏地址 请我喝杯茶~