百度筆試題3

http://hi.baidu.com/bbilu/blog/item/67129da248e524aecbefd0de.html

一、選擇題:15 10
1.
在排序方法中,關鍵碼比較次數與記錄地初始排列無關的是
.
A. Shell
排序 B. 歸併排序 C. 直接插入排序 D. 選擇排序


2.
以下多線程對int型變量x的操作,哪幾個需要進行同步:

A. x=y; B. x++; C. ++x; D. x=1;

3.
代碼

void func() {
static int val;

}
中,變量val的內存地址位於:

A.
已初始化數據段 B.未初始化數據段 C. D.


4.
同一進程下的線程可以共享以下

A. stack B. data section
C. register set D. thread ID

5. TCP
IP分別對應了 OSI中的哪幾層?

A. Application layer
B. Data link layer
C. Presentation layer
D. Physical layer
E. Transport layer
F. Session layer
G. Network layer

6. short a[100]
sizeof(a)返回?

A 2 B 4 C 100 D 200 E 400

7.
以下哪種不是基於組件的開發技術_____

A XPCOM B XP C COM D CORBA

8.
以下代碼打印的結果是(假設運行在i386系列計算機上):

struct st_t
{
int status;
short* pdata;
char errstr[32];
};

st_t st[16];
char* p = (char*)(st[2].errstr + 32);
printf("%d", (p - (char*)(st)));

A 32 B
114
C 120 D 1112

9. STL
中的哪種結構是連續形式的存儲
A map B set C list D vector

10.
一個棧的入棧序列是ABCDE,則棧的不可能的輸出序列是(

A
EDCBA BDECBA CDCEAB DABCDE

 

Answer

1D      2ABC  3A    4B       5EG    6D

7B       8C       9D      10C

2、第參考:http://www.diybl.com/course/3_program/c++/cppjs/2008717/133440.html

今天 看到一道百度筆試題

以下多線程對int型變量x的操作,哪幾個需要進行同步:

A. x=y;         B. x++;         C. ++x;            D. x=1;

 

最初有人說選B 因爲操作了2個寄存器。答案:ABC

後面乾脆將代碼彙編了。

得到

A

        movl    $1, -4(%ebp)

        movl    -4(%ebp), %eax

        movl    %eax, -8(%ebp)

B

        movl    $1, -4(%ebp)

        leal    -4(%ebp), %eax

        incl    (%eax)

C

        movl    $1, -4(%ebp)

        leal    -4(%ebp), %eax

        incl    (%eax)

D

        movl    $1, -4(%ebp)

我們看到ABC都對2個寄存器進行操作。

 

下表是一個多線程加鎖的規律表

  操作的結果與初值無關  操作的結果與初值相關

 寫簡單數據類型  不需要加鎖①  需要加鎖②

 寫複雜數據類型  需要加鎖③  需要加鎖④

 讀簡單數據類型  不需要加鎖⑤  不需要加鎖⑥

 讀複雜數據類型  需要加鎖⑦  需要加鎖⑧

可以同樣看到ABC都是寫簡單數據類型 並且操作的結果與初值相關。所以需要加鎖。即要求同步

2種情況的典型代表是“i++;”,需要對它加鎖是因爲它表面上雖然只有一條語句,卻要執行至少兩個操作,一是讀出i的初始, 二是把加一後的結果寫回去,兩個操作就沒有“原子性”了,所以需要加鎖.

 

4http://blog.csdn.net/hairetz/archive/2009/06/19/4281931.aspx

屬於同一進程的不同線程會共享進程內存空間中的全局區和堆,而私有的線程空間則主要包括棧和寄存器。因此,對於同一進程的不同線程來說,每個線程的局部變量都是私有的,而全局變量、局部靜態變量、分配於堆的變量都是共享的。在對這些共享變量進行訪問時,如果要保證線程安全,則必須通過加鎖的方式。

 

9http://www.cppblog.com/Herbert/archive/2009/05/30/70479.html

STL中的容器按存儲方式分爲兩類,一類是按以數組形式存儲的容器(如:vector deque);另一類是以不連續的節點形式存儲的容器(如:listsetmap)。

 

二、簡答題:20分,共2

1. 5分)重複多次fclose一個打開過一次的FILE *fp指針會有什麼結果,並請解釋。

考察點:導致文件描述符結構中指針指向的內存被重複釋放,進而導致一些不可預期的異
常。

Answer

http://topic.csdn.net/u/20080714/10/46ca253c-982a-4d80-9ee7-ec136ac7cae2.html

我感覺有可能導致錯誤(當然也有可能沒什麼反應,即你認爲的”成功“)。

每個進程都有一個句柄表,調用fclose會讓該文件句柄的計數減少1,如果該句柄的計數爲0,內核會在適當的時機收回該對象佔用的空間。

1 如果系統恰好收回了該空間,你又調用fclose,則可能會出問題。

2 句柄是個數字,比如你不用了數字爲20的句柄,那麼數字20就是空閒的了,再次創建新句柄時,可能會再次使用該數字,而如果你此時調用fclose(20),可能把別人跟關了。

這是我的理解。

 

2. 15分)下面一段代碼,想在調用f2(1)時打印err1,調用f2(2)時打印err4,但是代碼
中有一些問題,請做儘可能少的修改使之正確。

1 static int f1(const char *errstr, unsigned int flag) {
2 int copy, index, len;
3 const static char **__err = {“err1”, “err2”, “err3”, “err4”};

//改爲:static char _err[][5] = {"err1","err2","err3","err4"};
4
5 if(flag & 0x10000)
6 copy = 1;
7 index = (flag & 0x300000) >> 20;
8
9 if(copy) {
10 len = flag & 0xF;
11 errstr = malloc(len);        //*errstr = (char*)malloc(sizeof(char)*len+1);
12 if(errstr = NULL)    
13 return -1;
14 strncpy(errstr, __err[index], sizeof(errstr));
15 } else
16 errstr = __err + index;
17 }
18
19 void f2(int c) {
20 char *err;
21
22 swtch(c) {
23 case 1:
24 if(f1(err, 0x110004) != -1)

//err要返回字符串,那麼應該使用指向指針的指針

// if(f1(&err, 0x110004) != -1)
25 printf(err);
26 case 2:
27 if(f2(err, 0x30000D) != -1)

// if(f2(&err, 0x30000D) != -1)
28 printf(err);
29 }
30 }

 

Answer

#include <stdio.h>

#include <string.h>

#include <malloc.h>static int f1(char **errstr, unsigned int flag)

{

int copy, index, len;

    static char _err[][5] = {"err1","err2","err3","err4"};

if(flag & 0x10000)

{

   copy = 1;  

}

index = (flag & 0x300000) >> 20;

 

if(copy)

{

   len = flag & 0xF;

   *errstr = (char *)malloc(sizeof(char) * (len+1));

 

   if(0 == *errstr)

   {

    printf("err1");

    return -1;

   }   printf("%s/n",_err[index]);

   printf("%s/n",*errstr); 

   strncpy(*errstr, _err[index], len+1);

   printf("%s/n",*errstr);

 

   return 0;

}else

{

   *errstr = _err[index];

   return 0;

}

}

 

void f2(int c)

{

char *err;

err = 0;

switch(c)

{

   case 1:

    if(f1(&err, 0x010004) != -1)

    {

     printf("%s/n",err);

     break;

    }

   case 2:

    if(f1(&err, 0x30000D) != -1)

    {

     printf("%s/n",err);

     break;

    }

   default: break;

}

free(err);

}int main()

{

f2(1);

printf("/n");

f2(2);

return 0;

}

三、編程題:30 1

注意:要求提供完整代碼,如果可以編譯運行酌情加分。

 

1. 求符合指定規則的數。

給定函數d(n) = n + n的各位之和,n爲正整數,如 d(78) = 78+7+8=93 這樣這個函數

可以看成一個生成器,如93可以看成由78生成。

定義數A:數A找不到一個數B可以由d(B)=A,即A不能由其他數生成。現在要寫程序,找出

110000裏的所有符合數A定義的數。

輸出:

1

3

 

Answer

http://topic.csdn.net/t/20061009/09/5068554.html

方法1

#include   <iostream>  

  using   namespace   std;  

  bool   e[10000];  

  int   d   (int   n)  

  {  

          int   s=n;  

          while   (n)  

          {  

                      s+=n%10;  

                      n/=10;  

          }  

          return   s;  

  }  

  int   main()  

  {  

          int   i;  

          for   (i=0;i<10000;i++)  

          e[i]=false;  

          for   (i=1;i<10000;i++)  

          if   (d(i)<10000)  

          e[d(i)]=true;  

          for   (i=1;i<10000;i++)  

          if   (!e[i])  

          cout<<i<<endl;  

          return   0;  

  }  

 

方法2

void   main(void)  

  {  

        func(10000);  

  }   

  void   func(int   n)  

  {  

        for(int   i   =   1;   i   <=   n;   i++)  

        {  

              check(i);  

        }  

  }  

   

  void   check(int   n)  

  {  

        int   i   =   0,   j   =   0;  

        int   sum   =   0;   

        for(int   i   =   1;   i   <   n;   i++)       //這個地方有沒有更好的辦法判斷退出,減少循環?  

        {    

                sum   =   i;  

                for(j   =   i;   j   >   0;   j   /   10)  

                {  

                      sum   +=   j   %   10;  

                }  

                 

                if(sum   ==   n)  

                {  

                      break;  

                }          

        }  

        if(sum   !=   n)  

        {  

              printf("find   one!   n   =   %d",   n);  

        }  

  }  

 

 

 

 

 

 

 

 

四、設計題:35 1

注意:請儘可能詳細描述你的數據結構、系統架構、設計思路等。建議多寫一些僞代碼或

者流程說明。

 

1. 假設一個mp3搜索引擎收錄了2^24首歌曲,並記錄了可收聽這些歌曲的2^30URL,但每首歌的URL不超過2^10個。系統會定期檢查這些URL,如果一個URL不可用則不出現在搜索結果中。現在歌曲名和URL分別通過整型的SONG_IDURL_ID唯一確定。對該系統有如下需求:

1) 通過SONG_ID搜索一首歌的URL_ID,給出URL_ID計數和列表

2) 給定一個SONG_ID,爲其添加一個新的URL_ID

3) 添加一個新的SONG_ID

4) 給定一個URL_ID,將其置爲不可用。

限制條件:內存佔用不超過1G,單個文件大小不超過2G,一個目錄下的文件數不超過128個。

 

Answerhttp://topic.csdn.net/t/20061009/09/5068554.html

A1

內存不夠存儲這些url,所以將數據寫入若干個文件中。  

  每一首歌曲對應的存儲在文件中的信息格式爲(url1,   url2……)。  

  文件的總大小大約爲2^24*2^10*4   =2^36   =64GB.根據SongID即可計算出在哪個文件的哪個位置,那麼一個隨機的查詢操作耗時即是一次隨機打開文件並執行seek操作讀取數據的實際,大約是ms級別。  

struct

{

  int urlcount;

  int url[2^10];

}song[2^24];

整個結構的大小爲64g

   

  將每首歌曲的信息存入文件中,由於每首歌的url不超過2^10個,所以在文件中每首歌的存儲結構是2^10int數,每個int數字標識着一個url-1表示url不存在。初始化時將文件中每個int數初始化爲-1.  

  這樣每個SongID對應的信息佔用的空間爲2^10*4=4KB,設每個文件大小1G,那麼每個文件可存儲2^18=256KSong的信息。總共需要64個文件,把這些文件編號從0-63.  

   

  對於任意一個SongID,他所對應的url信息所在的文件編號是:SongID>>18,在文件中的位置是:(SongID&0x3FFFF)<<12

SongID一共24位,高6位對應於其url在哪個文件,一共2^6=64個文件;低18位對應其url在文件中的位置,每一個文件存儲2^18song信息)

   

  另外內存中用一個2^24大小的short int型數組來保存每一首歌曲對應的url的個數,計數組名爲urlCount[],初始化時值爲-1,表示對應的Song_ID不存在。此數組佔用空間2^25Byte=32MB;  

  url是否可用的信息用位圖來標識。位圖保存在內存中,佔用的空間爲2^30/8=2^27   Byte=128MB.

(關於位圖的知識,查看文件夾下面的基於Bloom-Filter 算法的URL 過濾器的實現.pdf

   

  對所要求的操作:  

  :1)         通過SONG_ID搜索一首歌的URL_ID,給出URL_ID計數和列表    

  通過SONG_ID計算出文件號和對應在文件中的位置,從urlCount[]中讀取url個數,讀出所有的url,並對每個url_ID查詢位圖看是否可用,若可用,將此url加入返回列表。  

   

  :2)         給定一個SONG_ID,爲其添加一個新的URL_ID    

  通過SONG_ID計算出文件號和對應在文件中的位置,設爲start,在通過urlCount[]得到url個數,假設有nurl,那麼將新的URL_ID寫入文件的start+sizeof(int)*n處。修改urlCount[SONG_ID]的值。  

   

  :3)         添加一個新的SONG_ID  

  檢查將對應的urlCount[SONG_ID],若爲-1,則修改爲0,若大於等於0,則表明該Song_ID已經存在。  

   

  :4)         給定一個URL_ID,將其置爲不可用    

  修改url位圖,標識URL_ID對應的位,表示爲不可用。

 

 

A2、一點想法  

  因爲“每首歌的URL不超過2^10個”,似乎在提示每個SONG_IDURL_ID佔用同樣的內存,那麼1g內存每個SONG_ID僅有64byte,而2^10URL_ID即使一個bit存一個,也需要128byte,顯然行不通的。  

   

  2^30URL_ID,即一個URL_ID最多1byte的內存。而由於每個SONG_ID佔用的內存不同,所以至少還得存儲這個信息。以最少信息論,假設每個URL_ID佔一個bit,則一個SONG_ID佔用內存的長度最大會有2^20bit(轉換成字節、字等佔用的內存更多,但計算會方便一些,快一些)...即長度最少要佔用21bit  

   

  另外,需要一個bit存一個URL_ID,至少還需要存一個MIN_URL_ID(然後第nbit1代表MIN_URL_ID+n這個URL_ID也屬於這個SONG_ID)SONG_ID因爲基本可以認爲不會刪除,所以不於保存,直接按index來。  

   

  也就是說,要存儲一個SONG_ID,至少需要內存   3221+URL_ID_CNT   bits.所以總內存需:  

   

  3221   ×   2^24     +   2^30     >   1G  

  <汗一個,寫到這裏忽然發現1G內存存1gURL_ID,很明顯直接就是不夠...>  

   

  所以,要佔用1g以下內存,基本上可以認爲需要用硬盤做數據交換,但似乎總感覺不爽,畢竟從題意上看,是不適合這樣的。當然了,1個文件2g最大,也不明白意思。直覺上認爲跟分佈運算有關。  

   

  PS:因爲URL_ID變化較大,(很可能隨時增加或者減少一個)所以不適合用連續存儲的方式。

 

 

 

A3

本人認爲可以採用建立兩個   song_id      url_id      B-Tree      ...,   其它的東西也許不需要細說了,   如那些放在內存中,   哪些放在文件中   ....   ,   熟悉軟件的人,   查一下數據結構和算法的書,   就可以了,   個人認爲這些東西只要理解就可以了,   不要去背,     Donald.E.Knuth   做東西也是查找和推論出來的,   ...  

發佈了35 篇原創文章 · 獲贊 0 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章