一道简单的阶层面试题

转载 2015年07月09日 21:13:49

首先声明:这篇是我转载而来,无意中看到很有感触:编程需要的是严谨的思维方式,草草了事得到的也只有草草的结果。


无论是技术笔试还是面试,通常会要求写一点代码或详细描述程序思路,很多应试者都认为自己的回答还算过得去,但往往还是没有了下文。究其原因,既有对试题的轻视,也有平时没有养成良好的思维习惯。其实无论试题的难易程度如何,其背后都可以考核出很多知识点来,比如我们来看这样一道简单的笔试题:

写程序,能够计算组合数

 

这道题太简单了,当我们第一次学程序设计语言的时候可能都写过这个程序,我们一起来看一下这道题的思路过程。

 

首先想到的是写一个求阶乘的函数,然后再另一个函数中对其调用以计算该组合数。这个思路没有问题,但是能写好代码也不是件容易的事,而且我们应该意识到,招聘方的这道简单的问题很显然是需要我们尽量写得完整的,而不是象征性写出思路,因此,必要的健壮性是要体现出来的。很多人的程序如下:

    privatestaticint factorial(int n){

       int ret=1;

       for(int i=2;i<=n;ret*=i++);

       return ret;

    }

   

    publicstaticint combination1(int all,int select){

       return factorial(all)/factorial(select)/factorial(all-select);

    }

 

在这段程序中,由于没有任何容错机制,所以肯定是得不到高分的。另外还有个别人在第二个函数中的语句写成了:

       return factorial(all)/factorial(select)*factorial(all-select);

这样粗心的错误直接会被判0分,基本上就不会再进入下一轮了。

 

加入了容错检查的程序如下:

    privatestaticint factorial(int n){

       if (n<0)

           thrownew InvalidParameterException();

      

       int ret=1;

       if (n==0 || n==1)

           return ret;

       else

           for(int i=2;i<=n;ret*=i++);

      

       return ret;

    }

   

    publicstaticint combination1(int all,int select){

       if (select>all || all<=0 || select<=0)

           thrownew InvalidParameterException();

      

       if (select==all)

           return 1;

      

       return factorial(all)/factorial(select)/factorial(all-select);

    }

这样这个基本思路的代码就算差不多了,这道题的及格分也就够了。

 

但是,在众多及格分的成绩中要想获得机会,还是需要再继续改进的。也有的是面试官不断的提出新的需求,比如:如果保持程序中使用int类型不变,那么上述阶乘的计算函数只能算到大约12!,还能进一步提高这个数值吗?或者如果让你提高这段代码的运行效率,你要用什么思路优化?

类似这样问题的提出,就是考验应聘者的时候了,经过分析,优化的空间可以通过原表达式约分实现。在原表达式中,必然有一部分阶乘是重复计算的,而且n!决定了可计算的最大值,如果能把这些重复的计算去掉,把阶乘运算去掉,很显然不仅效率能提高,而且可计算的范围也将变大。

参考程序如下:

    publicstaticint combination2(int all,int select){

       if (select>all || all<=0 || select<=0)

           thrownew InvalidParameterException();

      

       int ret=1;

       int begin=0;

       if (all==select)

           return ret;

      

       //1-begin之间的数被约分掉以简化计算

       if (select<all-select)

           begin=all-select+1;

       else

           begin=select+1;

      

       for(int i=begin;i<=all;ret*=i++);    //计算分子

       for(int i=all-begin+1;i>1;ret/=i--); //被分母除

      

       return ret;

    }

如果能第一次就写成这种思路,很显然,我们的机会会更多。

 

再来接受一下考验,如果面试官要求你再提供思路来优化运行效率,这时我们还要继续思考,比如把已经运算的结果缓冲起来,当再有相同的参数要求运算时直接从缓冲区返回算好的结果,将比重新运算要快。利用该思路,我们改造上边的函数,形成如下代码:

    privatestatic Map<String,Integer> mapTable=new HashMap<String,Integer>();

……

    publicstaticint combination3(int all,int select){

       if (select>all || all<=0 || select<=0)

           thrownew InvalidParameterException();

      

       int ret=1;

       int begin=0;

       if (all==select){

           return ret;

       }

      

       String tableKey=new String(all+","+select);

       Integer tableValue=mapTable.get(tableKey);

       if (tableValue!=null)

           return tableValue.intValue();

      

       if (select<all-select){

           begin=all-select+1;

       }

       else{

           begin=select+1;

       }

      

       for(int i=begin;i<=all;ret*=i++);

       for(int i=all-begin+1;i>1;ret/=i--);

      

       mapTable.put(tableKey, Integer.valueOf(ret));

      

       return ret;

}

利用一个Map作为缓冲区以保存曾经计算好的结果,典型的空间换时间的思路,但已经能让面试官满意的了。


阶层运算能考虑到这么多,确实非常厉害

史上最难的一道Java面试题

求下面这段程序的运行结果public class TestSync2 implements Runnable{ int b=100; synchronized void m1() ...
  • weixin_38553453
  • weixin_38553453
  • 2017年06月08日 15:31
  • 605

web前端一道很“坑”的js面试题

f = function() {return true;}; g = function() {return false;}; (function() {if (g() && [] == ![]) ...
  • k358971707
  • k358971707
  • 2017年02月23日 22:28
  • 989

前端程序员经常忽视的一个JavaScript面试题

前言 年前刚刚离职了,分享下我曾经出过的一道面试题,此题是我出的一套前端面试题中的最后一题,用来考核面试者的JavaScript的综合能力,很可惜到目前为止的将近两年中,几乎没有人能够完全答对,并非...
  • bluehire
  • bluehire
  • 2016年02月16日 13:27
  • 440

五个囚犯 一道真正难倒亿人的智力题,这是微软的面试题。

  5个囚犯,分别按1-5号在装有100颗绿豆的麻袋抓绿豆,规定每人至少抓一颗,而抓得最多和最少的人将被处死,而且,他们之间不能交流,但在抓的时候,可以摸出剩下的豆子数。问他们中谁的存活机率最大??提...
  • kj021320
  • kj021320
  • 2007年08月22日 02:34
  • 1489

又一道简单题

又一道简单题 Time Limit: 5000MS Memory Limit: 65535KB 64bit IO Format: SubmitStatusDescriptio...
  • qq_32792879
  • qq_32792879
  • 2016年08月23日 16:50
  • 260

java-多线程-一道阿里面试题分析

传说这是阿里的一道面试题: 也传说发这道题出来的作者去了tmail。下面是关于题目的描述:      这段代码大多数情况下运行正常,但是某些情况下会出问题。什么时候会出现什么问题?如何修正?可见博...
  • liguogangde
  • liguogangde
  • 2013年06月15日 22:44
  • 2438

一道很不错的js面试题

function Foo() { getName = function () { alert (1); }; return this; } Foo.getName = function...
  • java_goodstudy
  • java_goodstudy
  • 2016年12月04日 01:42
  • 1077

java面试题汇总记录

汇总了干开发以来遇到的面试题,便于查看~(仅供参考,错误请指正,需要更详细的解答请自行百度或谷歌) 1. 实现多线程方式 1、继承Thread类,重写run函数 2、实现Runnable接...
  • kuangtengda
  • kuangtengda
  • 2017年01月06日 15:32
  • 1768

一道很简单的题目

  昨天下课路过隔壁班的时候,他们的老师问了一个问题,说你输入一个数n,然后输出所有1,2,3组成的长度为n的组合,回来的时候吃晚饭的时候,想了想,其实问题很简单,回溯和递归就可以搞定,回实验室后立马...
  • tjltail
  • tjltail
  • 2007年03月27日 23:26
  • 696

一道简单的面试题

#include  using namespace std; int func(int x){ int countx = 0; while(x) { countx ++...
  • lovenanforever
  • lovenanforever
  • 2014年11月10日 21:05
  • 470
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:一道简单的阶层面试题
举报原因:
原因补充:

(最多只允许输入30个字)