面试姊妹篇2:有趣的BAT逻辑面试题分享

目的

  • 专门收集一些看上去很有意思的题目
  • 这些题目,一看就会,一做就错
  • 持续更新,每十题作为一篇文章

目录

系列文章

一、异或思维

1.1、在成对存在的数组中(即数组中的每个数必然存在另一个与其值相等的一个数),被程序员误插入了一个数(即该数在这个数组中唯一),如何找出这个数?

  • 答案:将所有数化为二进制,做异或

1.2、在成对存在的数组中(即数组中的每个数必然存在另一个与其值相等的一个数),被程序员误插入了两个数(即这两个数在这个数组中都是唯一),如何找出这两个数?

  • 答案:异或所有数,所得结果相当于混入的这两个数的异或,取其不为0的某一位,按照这一位将数组元素分成两组(一组为0,一组为1),两组组内异或,分别得到这两个数。

1.3、判断一个数是否为奇数?
答案:目前为止,最为简洁的两种方式如下:

方式一:
public static boolean isOdd(int i) {
    
    
    return i >> 1 << 1 != i;
}
方式二:
public static boolean isOdd(int i) {
    
    
    return (i & 1) == 1;
}

参考博客:
jdk那些类的底层实现使用过位运算

二、数组相关

2.1、给定一个数组a[],一次遍历在其中找出最大(最小)的元素。

  • 答案:冒泡排序。

2.2、给定一个数组a[],找出其中某两个数的和等于给定的一个数M。

  • 答案:首先快排(从小到大),然后头尾两个指针,若头尾指向的数之和大于M,尾指针减减,否则头指针加加。

2.3、给定一个数组a[],在其中找k个数(k>=2),使得其和等于给定的一个数M,没有返回false。

  • ​​​​​​​答案:动态规划的思想。

三、过桥问题

3.1、 四人过桥问题:速度设为v1,v2,v3,v4,满足v1>v2>v3>v4,单独过河时间满足:t1< t2 < t3 < t4,此时正在下雨,四人只有一把伞,于是两人共有一把伞过河,过桥速度以最慢的为主,过河后需要其中一个送伞回去,问如何安排过河时间最短?

答案:

  • 方案一:正常思维会认为v1速度最快,让他每次回头送伞最合适,于是v1分别与其他人过河再回头送伞,总时间:t2+t3+t4+2*t1。
  • 方案二:考虑到v1>v2>>>v3>v4(即v1、v2远远大于v3、v4),可以让v1、v2先过河,v1回头送伞,v3、v4一起过河,v2回头送伞,然后v1、v2再过河, 总时间:t2+t1+t4+t2+t2。综合考虑,本题回答动态规划为最佳答案。

四、随机问题

4.1、存在函数A()可以产生0~9 的随机数,且等概率的产生每个随机数,现在需要编写一个函数B(),使得产生数字1、2、3的概率为0.2,数字4的概率为0.4。
​​​​​​​答案:

public int B() {
    
    
    Switch(A()){
    
    
        Case 0, 6, 7, 8, 9:B();
        ​​​​​​​Case 1, 2, 3:Print(1or 2or 3); break;
        ​​​​​​​Case 4, 5:Print(4);break;
    }
}
或者
public int B() {
    
    
    Switch(A()){
    
    
        Case 01:Print(1);break;
        Case 23:Print(2);break;
        Case 45:Print(3);break;
        Case 6,7,89:Print(4);break;
    }
}

4.2、存在函数A()可以产生0~3 的随机数,且等概率的产生每个随机数,现在需要编写一个函数B(),使得产生数字1、2、3的概率为0.2,数字4的概率为0.4。
​​​​​​​答案:

public int B() {
    
    
    Switch((A(),A()){
    
    
        Case (0,0):Print(1);break;
        Case (0,1):Print(2);break;
        Case (0,2):Print(3);break;
        Case (0,3),(1,0):Print(4);break;
        case other:B();break;
    }
}

五、称重问题

5.1、四盒外观一模一样的巧克力豆,分别叫A、B、C、D,其中有一盒巧克力豆比其他盒都的要重一克,如何通过一次称量,找出这盒巧克力豆。
​​​​​​​答案:

  • 方法一:如果是显示重量的秤,则从第一盒取1个,第二盒取2个,第三盒取3个,第四盒取4个,重量比正常重几克就是第几盒。
  • 方法二:不显示重量的秤,每边放两盒,则能知道那边重,再分别取走一盒,看余下的是否平衡。

六、老鼠喝药问题

6.1、有1000瓶药水,里面只有一瓶毒药,老鼠喝下毒药后,会在刚刚一小时的时候死亡,现在给你10只老鼠和1个小时,请找出这瓶毒药(假设毒药量很大,可以分成很多份,并且不影响毒性)。

  • 因为只有一瓶药水,所以相对简单,首先对所有的药水编号1-1000,对老鼠编号1-10。
  • 十个老鼠前面放十个容器,盛药水,编号为x的药水,一定有一个二进制数(比如23号药水对应二进制:10111),因此把23号药水分别滴入第1号、第2号、第3号、第5号的老鼠容器内.
  • 做完前两步,分别让老鼠喝下去,1小时后,假设第x,y,z,k号小鼠死亡,那么毒药就是二进制为kzyx的那瓶,比如第2号、第3号、第5号、第7号老鼠死亡,对应的二进制为0001010110,因此第86号药水是毒药。

6.2、有1000瓶药水,里面只有一瓶毒药,老鼠喝下毒药后,会在刚刚一小时的时候死亡,现在给你2只老鼠和若干个小时,请找出这瓶毒药(假设毒药量很大,可以分成很多份,并且不影响毒性)。

  • 本题区别于上题是,只有两只小鼠,因此不能采用二进制了,换个思维,采用二维矩阵,我们把1000瓶药,放置成31*31=961、6*6=36、3,这样的三堆,前两个分别是两个矩阵。
  • 我们知道小鼠喝了毒药的情况下,在一小时的时候,也就是3600秒的时候,会死亡,那么我们根据不同的时间差,第一个小鼠在不同的时间喝矩阵的行混合物,第二只在不同时间段喝列的混合物。
  • 假设第一只在第一小时零15秒的时候死亡,说明第一个矩阵的第15行内有毒药,第二只在1小时30秒的时候死亡,说明第一个矩阵的第30列有毒药,那么第一个矩阵的(15,30)号药水是毒药,因为只有一瓶毒药,不存在跨矩阵的情况。

6.3、现在有1000瓶药水,但是这里面有多少瓶毒药不知道,老鼠喝了毒药,会在刚刚一小时的时候死亡,如何花费最少的小时数和最少的老鼠,测试出有多少毒药。

  • 本题区别于上题是,毒药数量不知道,如果采用二维矩阵,长度为x个老鼠,宽度为 y个老鼠,每个老鼠喝当前列或者当前行的药水混合物,那么 x+y 个老鼠是否可以测试出 x*y 瓶药?
    • 假设存在一瓶毒药,坐标为(x3,y5),那么一小时后,编号为x3和y5的老鼠会死亡
  • 那是不是说,假设存在k瓶毒药,我们根据死亡的小鼠来确定坐标就可以判断出来有多少瓶毒药了?
    • 然鹅并不是,假设存在这样一种情况,我们把k瓶毒药放置在矩阵所有的对角线上,一小时后,所有的小鼠全部死亡,能推断出来该矩阵全部有毒?
  • 如何才能有效呢?
    • 因为这道题是不知道多少瓶毒药,因此,存在一种可能性,有1000瓶毒药,那么最大需要1000只老鼠来测试,所以矩阵法失效,时间法也失效。
    • 目前一种比较实际的方法,但不一定是最好的方法是:1000瓶毒药放置成100*10的矩阵,用10只老鼠,按顺序每隔1秒喝当前列的100瓶药水中的一瓶,那么小鼠在某时间死亡,其后的药水需要重新进行测试。比如:100行*10列的药水,每一列编号1-100,第一只小鼠在第一秒喝第一瓶,第二秒喝第二瓶,假设一号小鼠在1小时56秒死亡,那么可以判定第一列的1-55瓶药水安全,56-100需要重新验证。

猜你喜欢

转载自blog.csdn.net/ljfirst/article/details/105884411
今日推荐