联系我

记一道"简单"的Java面试题

2020.06.20

面试题目

完成代码,判断一个整数是否是奇数。函数原型如下:

public boolean isOdd(int i)

不经思考的第一版代码

很多人不经思考,拿起键盘就开始写,会写出下面这样的代码:

public boolean isOdd(int i) {
    if (i % 2 == 1) {
        System.out.println("是奇数");
    } else {
        System.out.println("是偶数");
    }
}

编译错误,改正代码

很多人一运行,发现编译错误,发现是返回类型的问题,于是立马修改:

public boolean isOdd(int i) {
    if (i % 2 == 1) {
        return true;
    } else {
        return false;
    }
}

简化瘦身,第三版代码

其实很多人都会不假思索的写出上面的代码,这时有些面试官会引导面试者看看代码还有什么问题,如果面试者说本来就没什么问题,面试官会说:这个函数的定义要求返回一个什么类型的值?你判断表达式又是一个什么样的类型?此时如果面试者还是看不出问题来,那极有可能就直接被pass了,多数面试者会很快更改代码如下:

public boolean isOdd(int i) {
    return i % 2 == 1;
}

继续找问题,第四版代码

在以上代码的基础之上,面试官会接着发问:那我传进来一个-1呢?有些面试者可能会想了想之后嘴硬地表示他们从小被教导只有自然数才有奇数偶数之分,负数没有奇偶这一说。有些面试者则会接受面试官的设定,改成下面的代码:

public boolean isOdd(int i) {
    return i % 2 == 1 || i % 2 == -1;
}

优化,第五版代码

面试官:上面的代码可以继续优化吗?在简单的提示思考以后,聪明些的面试者可能会迅速改为下面的代码:

public boolean isOdd(int i) {
    return i % 2 != 0;
}

至此为止,代码就能够通过编译并且按照需求正确的运行了。实际上,能一开始写成这样的人并不多。

进一步思考,有没有更好的方案

面试官:我觉得取模操作比较慢,有更快的解决方案吗?这个时候,很多面试者心里的第一反应就是位运算了,稍微在心里一嘀咕,应该就能知道规律:奇数最后一位是 1,偶数最后一位是 0。于是写下下面的代码:

public boolean isOdd(int i) {
    return (i & 1) == 1;
}

最后的思考

上面的结果真的就比取模运算快吗?实际代码测试结果是,上面的按位与操作和取模操作实际运行的时间是差不多的,这是为什么呢?答案是:编译器会将对 2 的指数的取模操作,优化成位运算操作。

最后

从题目上看,这道题确实是一道简单的不能再简单的题目了,但最后却能挖出这么多问题来,说明的是我们在解决一个问题的时候,哪怕是一个非常简单的问题,都极能看出一个人的功底和思考的周密程度,程序员是一个讲究逻辑严谨的群体,我们需要深入的思考问题,而不是浅尝辄止。

参考文章

[1] https://zhuanlan.zhihu.com/p/57859872