百度2013校园招聘笔试题 个人答案分析

时间:2021-06-01 18:52:25
说明一下,编程题都是自己一点拙见,不免有很多 不到之处,错误的地方还请指出,一定认真修改。谢谢!

一、简答题

1.简述数据库以及线程死锁产生的原理及必要条件,简述如何避免死锁。

2.请列举面向对象设计的三个基本要素和五个主要涉及原则。

  三个基本要素:封装、继承、多态。

    五个基本原则:

              (1)单一职责原则:就一个类而言,应该仅有一个引起它变化的原因。

              (2)开放封闭原则:软件实体对外扩展开放,对修改封闭。

              (3)里氏替换原则:子类的实例能够替换父类的实例。

              (4)接口分离原则:采用多个专门的接口比使用单一的总接口要好。一个类对另一个类的 

                        依赖性建立在最小的接口上。

              (5)依赖倒置原则:依赖抽象不要依赖具体实现。、

3.简述Windows内存管理的几种方式及其优缺点。

 

1)块式管理。把主存分为一大块、一大块的,当所需的程序片段不在主存时就分配一块主存空间,把程序片段加载到主存,就算所需要的程序片段只有几个字节也只能把这块分配给它。优点:易于管理;缺点:浪费空间。

2)页式管理。把主存分为一页一页的,每一页的空间要比一块一块的空间小很多,显然这种方式的空间利用率要比块式管理高出很多。

3)段式管理。把主存分为一段一段的,每一段的空间又要比一页一页的空间小很多,这种方法在空间利用率上比页式管理高出很多,但也有另外一个缺点,一个程序片段可能会被分为几十个段,这样很多时间就会浪费在计算每一段的物理地址上。(I/O操作)

4)段页式管理。结合了段式管理和页式管理的优点。把主存分为若干页,每一页又分为若干段。

二、算法和程序设计

1.公司组织一次羽毛球比赛,采用淘汰机制,假设公司有1001个人,如果要评出“公司羽毛球第一高手”的称号,至少需要进行多少场比赛?请简述设计过程,并写出代码模拟比赛过程。

 /*
  * 分析: 我们可以分轮来比赛,每一轮都有2个人去比赛,如果总数(person)是奇数,
  *
  *       则有一个轮空,否则全部参与比赛,淘汰一半(person/2),剩余[person/2)+remain],
  *
  *       这里,remain=person%2.,淘汰的人数亦即比赛的场数,加起来就构成了比赛场
  *
  *       数。
  */

public static void main(String[] args) {

int person = 1001; //当然person一般是由用户来输入的。

int result = 0, remain;

while (person > 0 && person != 1) {

result += person / 2; // 进行了比赛==淘汰的人数

remain = person % 2; // 有没有人轮空

person /= 2; // 比赛后剩余的人数

person += remain; // 要加上轮空的人

}

System.out.println("共进行:" + result + "场比赛");

}

2.一百个灯泡排成一排,第一轮将所有灯泡打开;第二轮每隔一个灯泡关掉一个。即排在偶

数的灯泡被关掉,第三轮每隔两个灯泡,将开着的灯泡关掉,关掉的灯泡打开。依次类推,第100轮结束的时候,还有几盏灯泡亮着。

//哈哈,这道题是在宁波实习的时候有个网友问我的,不几天后就看到百度笔试有这道题,.

//真神奇啊!

//分析:

      

所有的台灯,只有摁下的次数是数,那么它一定是打开的,而对于台灯X,如果其前面有基数个X的约数,例如:

4=1*2*4

9=1*3*9

16=1*2*4*8*16

6=1*2*3*6 //偶数

因此,1~100内,查找X的约数个数为数的数X即为开着的台灯。


public static void main(String[] args) {

//编码就很简单了.

for(int i=1;i<100;i++){

if(hasOddOddNumer(i)){

System.out.print("  "+i);

}

}

}

private static boolean hasOddOddNumer(int data) {

boolean result = false;

int approximateNumberCount = 0;

for (int i = 1; i <= data; i++) {

if (0 == data % i) {

approximateNumberCount++;

}

}

if (0 != approximateNumberCount % 2) {

result = true;

}

return result;

}

3.假定有20个有序数组,每个数组有500个数字,数字类型32uint数值,现在需要取出

10000个数字中最大的500个,怎么做?

额,这个我看了别人给的方案,发现自己想错了,仅贴出别人的算法:

从20个数组中各取一个数,并记录每个数的来源数组,建立一个含20个元素的大根堆。
此时堆顶就是最大的数,取出堆顶元素,并从堆顶元素的来源数组中取下一个数加入堆,再取最大值,一直这样进行500次即可。
时间复杂度:500*log2(20)

 

三、系统设计题

手机上通常采用九键键盘输入。即:1-9个数字分别对应一定的英文字母(如:2对应ABC, 

3对应DEF...),因此,用户可以方便的输入中文内容。比如,用户输入“926”,可以对应

WXYZ”,“ABC"和”MNO“的一系列组合”WAN”,“YAN"、”ZAO“等,这些对应“万”,“严”,“早”

等汉字的中文拼音。

要求我们把这样的输入方式应用在我们的手机联系人查找功能上。有一个联系人列表

UserList,记录了(姓名,手机号)这样的组合,通过输入的数字字符串NumStr,按照下面

的规则把对应的联系人查找出来,返回一个ReaultList

规则:

1.手机号能连续部分匹配输入的数字字符串NumStr。如输入NumStr=926,则手机号为

13926811111会被查出来;

2.联系人姓名中的汉字转化成拼音后能够连续匹配输入数字字符串NumStr对应的英文字母

组合,如:输入NumStr=926,则联系人“王二”、“万事通”会被查找出来。因为“王二”的“王”的

拼音“WANG”中含有“WAN”,和“926”能匹配。 

输入:

联系人列表UserList<UserName, PhoneNo>;汉字拼音射射表Dict,数字拼音字符串

NumStr

输出:

符合规则的联系人列表ResultList<UserName, PhoneNo>

/*

   对于这种题,我不知道考察的是什么,其实我们应该可以*假设自己的条件吧,然后根据自己的步骤来做出判断,下面是我的一个思路,这个真不知道怎么样,还请高手们  不要笑话。
 */ 

Phone  phoneList<UserName, PhoneNo>存储了所有联系人的信息;

首先,我们获取“926对应的所有拼音可能组成一个列表:

       List<String> inputNameList=new ArrayList<String> ();

然后,把用户输入的字符串的所有可能addinputNameList。例如,926就有3*3*3种可能都add到inputNameList里面。
    

根据需求,用户名和手机号关键字都可能存在满足条件的情况,所以我们在一次遍历phoneList的情况下分别判断: (假设ResultList已经初始化,这里不再做实例化)

     for(Phone aPhone:phoneList ){

          //电话号码中是否含有字串 “926

         if(-1=aPhone.getPhoneNo().indexOf(NumStr)){

               ResultList.add(aPhone);

     }

      //我们根据姓获取姓的拼音aDict,然后遍历   

   //这个表,同样用字串截取的办法来判别。

      String aDict=aPhone.getUserName().getDict(); 

      for(String indexName :inputNameList){

               If(-1!=aDict.indexOf(indexName )){

                    ResultList.add(aPhone);

               }

      }

}

这样,这个ResultList就找到了。