百度質量部測試開發面試題

目錄javascript

Chap1 測試基礎 2html

Chap2 測試設計 4前端

Chap3 算法 12java

Chap4 設計題 19node

Chap5 邏輯題 21ios

Chap6編程及代碼題 26c++

Chap7 計算機基礎 38git

1. C/C++ 38程序員

2. JAVA 39web

3. 多線程: 40

4. 網絡編程 41

5. Linux 43

Chap 8 項目和背景 47

Chap9 外部工具 48

1. Selenium 48

2. Ruby-Watir 49

3. QTP: 50

4. LoadRunner 51

 


Chap1 測試基礎

附件1的19-21頁是一個模擬的面試場景,其中有很多經典題型和問題。不過已經在網上廣爲流傳,建議瞭解其中面試思路爲主,題目不要照搬太多。

  1. 黑盒測試和白盒測試經常使用的測試方法有哪些?舉例說明。

答:白盒測試:邏輯覆蓋法,主要包括語句覆蓋,判斷覆蓋,條件覆蓋,判斷條件覆蓋,條件組合覆蓋、路徑覆蓋。

黑盒測試:等價劃分類,邊界值分析,錯誤推測法等

  1. 靜態測試和動態測試的概念。

答:靜態方法是指不運行被測程序自己,僅經過分析或檢查源程序的語法、結構、過程、接口等來檢查程序的正確性。對需求規格說明書、軟件設計說明書、源程序作結構分析、流程圖分析、符號執行來找錯。靜態方法經過程序靜態特性的分析,找出欠缺和可疑之處,例如不匹配的參數、不適當的循環嵌套和分支嵌套、不容許的遞歸、未使用過的變量、空指針的引用和可疑的計算等。靜態測試結果可用於進一步的查錯,併爲測試用例選取提供指導。

動態方法是指經過運行被測程序,檢查運行結果與預期結果的差別,並分析運行效率和健壯性等性能,這種方法由三部分組成:構造測試實例、執行程序、分析程序的輸出結果。所謂軟件的動態測試,就是經過運行軟件來檢驗軟件的動態行爲和運行結果的正確性。目前,動態測試也是公司的測試工做的主要方式。根據動態測試在軟件開發過程當中所處的階段和做用,動態測試可分爲以下幾個步驟:一、單元測試 二、集成測試 三、系統測試 四、驗收測試 五、迴歸測試。

  1. 等價類有幾種,含義分別是什麼?

答:等價類分爲如下幾類:

  • 有效等價類和無效等價類
  • 有效等價類就是對程序的規格說明有意義的,合理的輸入數據所構成的集合,利用有效等價類可驗證程序是否實現了規格說明中的功能和性能。
  • 無效等價類是那些對程序的規格說明不合理或者無心義的數據所構成的,爲了驗證程序作其不該做的事情。
  1. 等價類劃分的優缺點。(答出一些使用過程當中的體會便可)

答:優勢:考慮了單個數據域的各種狀況,避免盲目或隨機的選取輸入數據的不完整性和不穩定性,同時可有效控制測試設計的數量。

缺點:對組合狀況考慮不足,同時等價類劃分基於等價類中的輸入都能產生相同的效果,在不少狀況下用例選擇不當會產生問題(如邊界)。

  1. 邊界值測試方法的優缺點。

答:長期的測試工做經驗告訴咱們,大量的錯誤是發生在輸入或輸出範圍的邊界上,而不是發生在輸入輸出範圍的內部。所以針對各類邊界狀況設計測試用例,能夠查出更多的錯誤。

不過邊界值分析法與等價類劃分法同樣,沒有考慮輸入之間的組合狀況,所以須要進一步結合其餘測試用例設計方法。

  1. 等價類劃分的原則(瞭解大概便可,關鍵看是否會使用)

答:等價類劃分的原則以下:

  • 在輸入條件規定了取值範圍或值的個數的狀況下,則能夠確立一個有效等價類和兩個無效等價類.
  • 在輸入條件規定了輸入值的集合或者規定了「必須如何」的條件的狀況下,可確立一個有效等價類和一個無效等價類.
  • 在輸入條件是一個布爾量的狀況下,可肯定一個有效等價類和一個無效等價類.
  • 在規定了輸入數據的一組值(假定n個),而且程序要對每個輸入值分別處理的狀況下,可確立n個有效等價類和一個無效等價類.
  • 在規定了輸入數據必須遵照的規則的狀況下,可確立一個有效等價類(符合規則)和若干個無效等價類(從不一樣角度違反規則).
  • 在確知已劃分的等價類中各元素在程序處理中的方式不一樣的狀況下,則應再將該等價類進一步的劃分爲更小的等價類.
  1. 性能測試:如何評價系統的極限性能?

答: 基本點:併發度、響應時間、單位時間吞吐量、系統穩定性、多場景。

加分點:新舊版本對比,性能瓶頸分析方法(雪崩、線性拐點等)。

  1. 判斷測試活動停止的條件

答:從如下幾個角度分析,包括:無新發生bug且嚴重性高的老bug已修復;bug收斂;某一級別bug低於必定比例;時間耗盡;知足特定覆蓋率。另外,能夠說說在之前的項目測試是如何結束的。

  1. 常見測試模型?

答:常見的軟件測試模型包括V模型、W模型、H模型、X模型和前置模型。([注]:具體解釋太長了,見附件1的前幾頁。)


Chap2 測試設計

  1. 配置文件測試設計

題目:一個程序須要根據配置文件,將本地的多個文件(model.0, model.1, model.2…)分發到不一樣機房的不一樣機器上去。其中,配置文件格式以下:

#機房數量

SITE_NUM : 5

#第0個機房機器數量

SITE_0_HOST_NUM : 10

#該機房第n個機器的ip

SITE_0_HOST_0 : 192.168.0.1

SITE_0_HOST_1 : 192.168.0.2

。。。

SITE_0_HOST_9 : 192.168.0.10

 

SITE_1_HOST_NUM : 10

SITE_1_HOST_0 : 192.168.1.1

SITE_1_HOST_1 : 192.168.1.2

。。。

 

#文件數量

MODEL_NUM : 5

#第n個文件在第m個機房須要的備份數

MODEL_0_REP_NUM : 0 : 3, 1 : 3,2:3, 3:3:4:3

MODEL_1_REP_NUM : 0 : 3, 1 : 3,2:3, 3:3:4:3

MODEL_2_REP_NUM : 0 : 3, 1 : 3,2:3, 3:3:4:3

MODEL_3_REP_NUM : 0 : 3, 1 : 3,2:3, 3:3:4:3

MODEL_4_REP_NUM : 0 : 3, 1 : 3,2:3, 3:3:4:3

 

分發要求:一臺機器上不能佈置多份相同的文件

每臺機器上要求分發的文件數量儘可能均勻

問題:請設計測試用例。

答:各類邊界值;不一樣機器的IP重複;在某機房的須要的備份數超過了機器數;

  1. 杯子的測試(校招)

答:冒煙測試:速度裝一杯水,是否漏水

功能測試:漏水測試,透明度測試,衛生狀況測試,杯口平滑測試,重量測試,均勻度測試

壓力測試:抗摔測試,抗高溫測試

歡迎添加

  1. 描述bs這類模塊的功能,設計測試用例【標記】
  2. strstr測試(能夠擴展到其餘函數測試,主要考察邊界,基本狀況,魯棒性,性能等方面是否考慮全面,實習生2面)

答:基本狀況;邊界值;魯棒性;性能以及其算法優化;

  1. 請使用等價類劃分的測試方法完成用例設計。

題目: 設有一個檔案管理系統,要求用戶輸入以年月表示的日期。假設日期限定在1990年1月~2049年12月,並規定日期由6位數字字符組成,前4位表示年,後2位表示月。

問題:現用等價類劃分法設計測試用例,來測試程序的"日期檢查功能"。

答:

  • 劃分等價類並編號,下表等價類劃分的結果

輸入等價類

有效等價類

無效等價類

日期的類型及長度

6位數字字符

有非數字字符

 

 

少於6位數字字符

 

 

多於6位數字字符

年份範圍

在1990~2049之間

小於1990

 

 

大於2049

月份範圍

在01~12之間

等於00

 

 

大於12

  • 設計測試用例,以便覆蓋全部的有效等價類在表中列出了3個有效等價類,編號分別爲①、⑤、⑧,設計的測試用例以下:

測試數據    指望結果      覆蓋的有效等價類

200211      輸入有效      ①、⑤、⑧

爲每個無效等價類設計一個測試用例,設計結果以下:

測試數據   指望結果     覆蓋的無效等價類

95June     無效輸入          ②

20036      無效輸入          ③

2001006    無效輸入          ④

198912     無效輸入          ⑥

200401     無效輸入          ⑦

200100     無效輸入          ⑨

200113     無效輸入          ⑩

  1. CP 命令設計測試用例(5分鐘)

答:主要從異常、功能和性能三方面考慮:

  • 異常

參數異常:源和目標參數異常:包含特殊字符;參數超長;指定的位置實際不存在

拷貝對象異常:非法的執行權限;存儲介質有損壞;非法的文件格式和內容

執行過程異常:拷貝到一半斷電;拷貝過程當中硬盤滿;拷貝過程當中源或目的被刪除

  • 功能
    • 文件

不一樣文件大小:0,1k,10k。。。

不一樣的文件類型:文本,二進制,設備文件。。。

  • 目錄

包含各類文件類型

包含子目錄,目錄深度

目錄文件數量不少

針對文件和目錄分別驗證拷貝的準確性,完整性。

  • 性能
    • 場景:

拷貝大文件

拷貝目錄中存在大量小文件

跨文件系統間拷貝

跨存儲介質間拷貝(硬盤到U盤。。。)

構造源的各類磁盤分佈(磁盤扇區分佈。。。)

併發執行拷貝

  • 關注的性能點:拷貝時間, CPU,內存,磁盤IO
  1. 如何測試模板10分鐘)

題目:百度首頁是由模板展示,請問如何對它進行測試;

要求:不須要考慮性能相關因素。建議多從用戶行爲和使用環境角度進行測試

(考察點:測試能力+思惟系統性+思惟發散性)

答:

展示檢查:文字圖片內容,連接,一致性

數據傳遞:字符串長短與截斷;特殊字符;中英文;空格;下拉條提示

兼容性檢查:不一樣瀏覽器,不一樣操做系統,不一樣分辨率

用戶行爲:窗口拉大,放小;字號大小;編碼格式;刷新;前進後退

  1. 白盒測試對子程序進行測試(15分鐘)

題目:本流程圖描述了某子程序的處理流程,現要求用白盒測試法對子程序進行測試。

要求:根據白盒測試經常使用的如下幾種方式:語句覆蓋、斷定覆蓋、條件覆蓋、斷定/條件覆蓋、多重條件覆蓋(條件組合覆蓋)、路徑覆蓋六種覆蓋標準,從供選擇的答案中分別找出知足相應覆蓋標準的最小的測試數據組並簡述各類測試方法。

 

 

供選擇的答案

x=3 y=3 z=0;x=1 y=2 z=1

x=1 y=2 z=0;x=2 y=1 z=1

x=4 y=2 z=0; x=3 y=3 z=0; x=2 y=1 z=0; x=1 y=1 z=1

x=4 y=2 z=0; x=1 y=2 z=1; x=2 y=1 z=0; x=1 y=1 z=1

x=4 y=2 z=0

x=4 y=2 z=0;x=1 y=1 z=1

參考答案:

  • 語句覆蓋E:語句覆蓋是指選擇足夠的測試用例,使得運行這些測試用例時,被測程序的每一個語句至少被執行一次,語句覆蓋是一種比較弱的覆蓋標準
  • 斷定覆蓋A:也稱分支覆蓋,是指選擇足夠的測試用例,使得運行這些測試用例時,被測程序的每一個斷定的全部可能結果至少出現一次
  • 條件覆蓋B:是指選擇足夠的測試用例,使得運行這些測試用例時,斷定中的每一個條件的全部可能結果至少出現一次
  • 斷定/條件覆蓋F:是指選擇足夠的測試用例,使得運行這些測試用例時,斷定中每一個條件的全部可能結果至出現一次,而且每一個斷定自己的全部可能結果也至少出現一次
  • 多重條件覆蓋D:是指選擇足夠的測試用例,使得運行這些測試用例時,每一個斷定中條件結果的全部可能組合至少出現一次
  • 路徑覆蓋C:是指選擇足夠的測試用例,使得運行這些測試用例時,程序的每條可能執行到的路徑都至少通過一次
  1. Baidu hi 聊天消息收發的測試思路(10分鐘)

問題:請給出BAIDU hi聊天消息收發的測試思路?(10分鐘)

(考察點:基本測試思路)

參考答案:主要從如下幾個方面來考察:正常測試、異常測試、不一樣的消息類型、組合測試、長度極值、是否延遲、是否丟失、是否被篡改、安全性

  1. 登陸界面測試(10分鐘)

 

參考答案:但願能夠對測試點作分類劃分,如功能、UI、性能、安全

  1. 測試自動販賣機 (20分鐘)

題目: 測試自動販賣機,場景:販賣機將用在露天的繁華的大街上

(考察點: 主要考察邏輯思惟、思惟的發散性)

參考答案: 

大概能夠從如下幾個方面來考慮:

  • 考慮到管理員的功能:如添加貨物功能、訂價等功能
  • 考慮到界面外觀、用戶說明的
  • 容錯考慮比較多的
  1. 三角形測試(20分鐘)

題目:一個程序,從輸入框中讀取三個整數值,這三個數值表明了三角形三邊的長度。程序顯示提示信息,指出該三角形到底是不規則三角形、等腰三角形仍是等邊三角形。(注:不規則三角形指三角形中任意兩邊不相等,等腰三角形指有兩條邊相等,等邊三角形指三條邊相等)

要求:假設你將做爲一名測試工程師對該程序進行測試,你會採用什麼方法進行測試用例設計?請寫出你採用的方法、測試用例設計的過程以及最後的測試用例。(30分鐘)

(考查點:考察測試思惟的嚴謹性,答全難)

參考答案:能夠採用等價類劃分的方法進行測試用例的設計。

  • 等價類表:

輸入條件

有效等價類

無效等價類

是否三角形的三條邊

⑴A>0

⑺A<=0

⑵B>0

⑻B<=0

⑶C>0

⑼C<=0

⑷A+B>C

⑽A+B<=C

⑸B+C>A

⑾B+C<=A

⑹A+C>B

⑿A+C<=B

是否等腰三角形

⒀A=B

⒃A!=B&&B!=C&&C!=A

⒁B=C

⒂C=A

是否等邊三角形

⒄A=B&&B=C&&C=A

⒅A!=B

⒆B!=C

⒇C!=A

  • 測試用例:

序號

[A,B,C]

覆蓋等價類

輸出

1

[3,4,5]

⑴⑵⑶⑷⑸⑹

通常三角形

2

[0,1,2]

不能構成三角形

3

[1,0,2]

4

[1,2,0]

5

[1,2,3]

6

[1,3,2]

7

[3,1,2]

8

[3,3,4]

⑴⑵⑶⑷⑸⑹⒀

等腰三角形

9

[3,4,4]

⑴⑵⑶⑷⑸⑹⒁

10

[3,4,3]

⑴⑵⑶⑷⑸⑹⒂

11

[3,4,5]

⑴⑵⑶⑷⑸⑹⒃

非等腰三角形

12

[3,3,3]

⑴⑵⑶⑷⑸⑹⒄

等邊三角形

13

[3,4,4]

⑴⑵⑶⑷⑸⑹⒁⒅

非等邊三角形

14

[3,4,3]

⑴⑵⑶⑷⑸⑹⒂⒆

15

[3,3,4]

⑶⑷⑸⑹⒀⒇

 

  1. 較複雜功能程序設計用例(30分鐘)

程序從標準輸入中讀取,判斷輸入字符是固定電話號碼或者手機號碼

         a) 手機號碼:以13開頭,長度爲11的連續數字

         b) 固定電話號碼:固定電話號碼包括區號和號碼兩部分,其中號碼爲長度爲7或8,而且不以0開頭的連續數字。區號可有可不有。區號和號碼間可有「-」,也能夠沒有。

         c) 當用戶輸入完畢後,系統返回的答案包括: 手機號碼 固定號碼 無正確電話號碼

         d) 一次輸入中若是有多個正確號碼(空格爲分割符),以最後一個正確號碼的類型爲準

對實現上述功能的程序設計測試用例。(40分鐘)

區號範圍(x表示任意數字):

3位區號

4位區號

10

03××

20

04××

21

05××

22

06××

23

07××

24

08××

25

09××

27

 

28

 

29

 

參考答案: 如下是測試設計的參考思路:

有空格

空格在兩頭

中間有正確電話號碼

 

 

 

中間無正確電話號碼

 

 

 

中間無字符

 

 

空格在中間

一個空格

最後一個爲錯誤手機號

 

 

所有爲錯誤手機號

 

 

最後一個爲正確手機號

 

 

多個空格

最後一個爲正確手機號

 

 

第一個爲正確手機號

 

 

所有爲錯誤手機號

 

 

超長字符含空格

 

 

 無空格

只含數字

以0開頭

前三位是區號

區號識別

前三位非區號

前四位爲區號

區號識別

前四位非區號

 

非0開頭

13開頭

長度爲11

長度非11

座機號碼

非座機號碼

非13開頭

座機號碼識別

含數字和-

一個-

-前是區號

-後爲座機

-後非座機

-前非區號

-後爲座機

多個-

含其餘字符

超長字符不含空格

空輸入

 

 

 

 

 

 

座機識別

 

 

 

 

 

首位爲0

長度爲6

全部數字均能被識別??

 

 

長度爲7

 

 

 

 

長度爲5

 

 

 

 

長度爲8

 

 

 

 

首位非0

 

 

 

 

 

 

 

 

 

 

 

 

 

區號識別

 

 

 

 

 

三位長度

010開頭

 

 

 

02開頭

026開頭

 

 

 

非026

 

 

 

非0十、02開頭

011開頭

 

 

 

030開頭

 

 

 

四位長度

03-09開頭

 

 

 

01

 

 

 

02

 

 

 


Chap3 算法

  1. 請列舉的經常使用排序算法,並說明其時間複雜度,並說明排序思想。

答:

  • 冒泡排序:兩兩比較待排序數據元素的大小,發現兩個數據元素的次序相反時即進行交換,直到沒有反序的數據元素爲止。算法時間複雜度是O(n^2)。
  • 選擇排序:每一趟從待排序的數據元素中選出最小(或最大)的一個元素,順序放在已排好序的數列的最後,直到所有待排序的數據元素排完,算法複雜度是O(n^2)。
  • 插入排序:每次將一個待排序的數據元素,插入到前面已經排好序的數列中的適當位置,使數列依然有序;直到待排序數據元素所有插入完爲止。算法時間複雜度是O(n^2)
  • 快速排序:在當前無序區R[1..H]中任取一個數據元素做爲比較的"基準"(不妨記爲X),用此基準將當前無序區劃分爲左右兩個較小的無序區:R[1..I-1]和R[I+1..H],且左邊的無序子區中數據元素均小於等於基準元素,右邊的無序子區中數據元素均大於等於基準元素,而基準X則位於最終排序的位置上,即R[1..I-1]≤X.Key≤R[I+1..H](1≤I≤H),當R[1..I-1]和R[I+1..H]均非空時,分別對它們進行上述的劃分過程,直至全部無序子區中的數據元素均已排序爲止。不穩定,最理想狀況算法時間複雜度O(nlog2n),最壞O(n^2)。
  • 堆排序:堆排序是一樹形選擇排序,在排序過程當中,將R[1..N]當作是一顆徹底二叉樹的順序存儲結構,利用徹底二叉樹中雙親結點和孩子結點之間的內在關係來選擇最小的元素。算法時間複雜度O(nlogn)。
  • 希爾排序:其實就是用步長控制的插入排序,希爾排序經過加大插入排序中元素之間的間隔,並在這些有間隔的元素中進行插入排序,從而讓數據項能夠大幅度移動,這樣的方式能夠使每次移動以後的數據離他們在最終序列中的位置相差不大,保證數據的基本有序,大大提高了排序速度,運算時間複雜度N*logN。
  • 歸併排序:

Divide: 把長度爲n的輸入序列分紅兩個長度爲n/2的子序列。

Conquer: 對這兩個子序列分別採用歸併排序。

Combine: 將兩個排序好的子序列合併成一個最終的排序序列。

時間複雜度是O(nlog2n)。

  1. 快速排序的平均時間複雜度是多少?最壞時間複雜度是多少?在哪些狀況下會遇到最壞的時間複雜度。

答:

快速排序的平均時間複雜度O(nlog2n),最壞時間複雜度O(n^2)。

最壞狀況:當每次pivot選擇剛好都把列表元素分紅了(1,n-1)

採起措施:pivot的選取是經過random來進行

  1. 各個排序算法的穩定性,並給出理由。

答:

選擇排序、快速排序、希爾排序、堆排序不是穩定的排序算法,而冒泡排序、插入排序、歸併排序和基數排序是穩定的排序算法。

參考:http://hi.baidu.com/cuifenghui/blog/item/0587932b039557f9e7cd4051.html

  1. 兩個單項鍊表求交點。

單向鏈表有交點意思是交點後的節點都是同樣的;所以,若是兩個單向鏈表相交,是成Y字形的。

思路:求出第一個鏈表長m,第二個長n。假設m>=n,那麼就去掉第一個鏈表的前m-n個元素,使之等長,而後依次比較第一個、第二個、第三個元素,直到找到或者結束。

NODE* FindNode(NODE* pHead1, NODE* pHead2)

{

    NODE* p1 = pHead1;

    NODE* p2 = pHead2;

    int i = 1, j = 1, k = 0, f = 0;

    if(pHead2 == NULL || pHead2 == NULL)

    {

        return NULL;

    }

    while(p1->next != NULL)

    {

        p1 = p1->next;

        i++;

    }

    while(p2->next != NULL)

    {

        p2 = p2->next;

        j++;

    }

    if(p1 != p2)

    {

        return NULL;        //若是尾節點不一樣,直接返回 NULL

    }

    else                   //不然尋找第一個相同的節點

    {

        p1 = pHead1;                // 1

        p2 = pHead2;                // 2

        f = fabs(i, j);   //計算兩條鏈表長度的差

        if(i > j)         //若是第一個鏈表比第二個長,第一個鏈表先向前移動f

        {

            for(k=0; k<f; k++)

            {

               p1 = p1->next;

            }

            while(p1 != p2)

            {

                p1 = p1->next;

                p2 = p2->next;

            }

            return p1;

        }

        else

        {

            for(k=0; k<f; k++)

            {

                p2 = p2->next;

            }

            while(p1 != p2)

            {

                p1 = p1->next;

                p2 = p2->next;

            }

            return p1;

        }

    }

}

 

  1. 遞增數列中每一項均可以表示爲3^i*5^j*7^k0<=i,j,k),即1,3,5,7,9,15,21,25,27…,實現算法,求出該數列中的第n

答:

先放置幾個隊列:

L1: 3^i (i >=0)

L2: 3^i * 5^j  (j >= 1)

L3: 3^i * 5^j * 7^k (k >= 1)

Step1: 清空三個隊列、分別把3,5,7放入三個隊列的首位。準備一個新隊列L(目前爲空)。

Step2: 比較三個隊列的頭,找出最小的那個。把這個元素從隊列出隊,並加到L的尾部。

Step3:

若是Step2中的元素是從L1中獲取的,假設是3^m,則在L1的尾部加入3^(m+1),L2的尾部加入3^m*5,L3的尾部加入3^m*7。

若是Step2中的元素是從L2中獲取的,假設是3^m * 5^n,則在L2的尾部加入3^m * 5^(n+1),L3的尾部加入3^m * 5^n *7。

若是Step3中的元素是從L3中獲取的,假設是3^m * 5^n * 7^p,則在L3的尾部加入3^m * 5^n * 7^(p+1)。

Step4: L的長度到達N了嗎?若是沒到達,重複L2-L4。若是到達,則進行L5。

Step5: 取得L的末尾元素,即爲所求。

  1. 爲二叉樹中每個節點創建他的右鄰居節點(能夠不屬於同一個父節點),要求遞歸與非遞歸都實現,如

                A

              /   \

          B  -----> C

        /           /  \

      E-----> F -> G

答:

  • 遞歸:

buildRightSibling(Linkedlist list)

{

  Linkedlist nextlevel = new Linkedlist();

  把list中的每一個元素的子節點,放入nextlevel中。

  //list中每一個元素,設置右鄰結點,指向list中的下一個元素

  //這一步能夠在鏈表中就實現掉。

  If(nextlevel == null || nextlevel.length() ==0)

    Return;

  Else

buildRightSibling(nextlevel);

}

//啓動函數

buildRightSibling(new Linkedlist(root));

 

  • 非遞歸

層序遍歷每一層,對每個元素都打上標記。好比(1,1)表明第1層第1個元素。

全部元素都打上標記之後,對每一個元素(m,n)都尋找(m,n+1)元素

  1. 走臺階問題,一次能夠走123級,都N級臺階的方法數。

答:

初始:f(0) = 0;  f(1) =1;  f(2) = 1 + 1 = 2;

遞推公式:f(n) = f(n - 1) + f(n-2) + f(n - 3)

  1. 10進制數轉2進制數,

題目:2進制除了0,1,還能夠用2表示。例如:

1-> 1

2-> 10 or 02

3->11

4 ->100 or 020 or 012

問題:這樣一個十進制數轉爲二進制數,就不是惟一的了。現求十進制數N轉換爲這種二進制數的全部表示方法數。

答:

f(0)=1, f(1)=1, f(2)=2,

f(n) = f( (n-1)/2) 當n爲奇數

       = f(n/2)+f((n-2)/2 )當n爲偶數

  1. 一個環狀鏈表(收尾相連),兩個指針head1head2從同一個節點出發,head1每次走一步,head2每次走兩步,請證實,兩個指針第一次相遇於出發的節點

答:

設兩個指針走的次數爲x,使用簡單的數學公式便可證實。難度1面。考察基本的數學 知識。

設鏈表有m個元素,head1在第一次相遇時走了n步,c爲head1和head2第一次相遇的節點距離出發節點的距離。

則: head1走過的路程爲 c = n;

head2走過的路程爲 c + k *m = 2n; (k爲整數)

所以,c = k*m,即c剛好是鏈表長度的整數倍,即兩個指針第一次相遇必定是在出發的節點。

  1. 一個鏈表中含有環。請找出環的起始節點

答:

方法1: 使用標記法,走過的節點標記1。使用這種方法,須要時間/空間複雜度O(n)

方法2: 使用第6題的思路,設兩個指針走的次數爲x便可獲得,時間複雜度不變,但空間 複雜度爲O(1)。難度1面,考察可否使用已經掌握的知識(第一題)來求解。

讓兩個指針head1和head2從同一個節點出發,head1每次走一步,head2每次走兩步,當兩者重合時,讓head2回到鏈表的頭部,以每次一步的步長走,當head1和head2再次相遇時,就是環路的起始節點了。

  1. 給定N個數,其中有一個數的出現次數超過N/2,請找出這個數,On)算法

(考察點:該數出現次數超過其餘全部數出現次數總和,使用計數方式解答。難度:2面)

答:

解法1: 開一個新的列

比較第1,2個數字。若是相同,則放入新的列中 若是不一樣,則兩個都丟棄

而後比較第3,4個數字,5,6個數字

這個時候 新的列 最長爲n/2 (實際上會遠遠更短)

而後對新的列 如法炮製 再次縮短一半

當某個時刻 列的長度是1或者列忽然消失時候 結束

長度爲1 說明這個就是的。消失,說明不存在大於n/2的個數的數

解法2:

構造一個hashtable,其中key是這個N個數的值,而value則是他們出現的次數;

最後遍歷這個hashtable,找出最大的便可。[ZhaiYao: 這個方法應該很差。不該該使用hashtable]

  1. 最長連續子序列之和(和最接近0的子序列),環形數組的最大子序列和。

答:

環形的拼成2n的數組後求解。

最長連續子序列之和:掃描數組,從左到右記錄當前子序列的和ThisSum,若這個和不斷增長,那麼最大子序列的和MaxSum也不斷增長(不斷更新MaxSum)。若是往前掃描中遇到負數,那麼當前子序列的和將會減少。此時ThisSum 將會小於MaxSum,固然MaxSum也就不更新。若是ThisSum降到0時,說明前面已經掃描的那一段就能夠拋棄了,這時將ThisSum置爲0。而後,ThisSum將從後面開始將這個子段進行分析,如有比當前MaxSum大的子段,繼續更新MaxSum。這樣一趟掃描結果也就出來了。

和最接近0的子序列:【標記】

環形數組的最大子序列之和:將環形數組首尾拼接成一個2n的線型數組(如環形數組 0 1 2, 能夠拼接成 0 1 2 0 1 2),按1)的方法能夠找到最大連續子序列之和

  1. 字符串按字母a-z排序

         題目要求:

          (1)不是用排序庫函數;

          (2)代碼實現;

          (3)算法複雜度估算;

          (4)測試本身的代碼;

          (5)可否用另外一種排序方式,比較優缺點;(plus)

答:

1char *sort(char *a){

        int i, j;

        char tmp;

        for( i = 0; a[i] != '\0'; i++){

                for( j = i + 1; a[j] != '\0'; j++){

                        if(a[i] > a[j]){

                                tmp = a[i];

                                a[i] = a[j];

                                a[j] = tmp;

                        }

                }

        }

2. 算法複雜度:輸入爲一個n個字符的字符串,則複雜度爲O()

3. 另外一種排序算法:快排,複雜度O(nlgn) [ZHAIYAO:可不能夠用另外一種方式?開一個26長的數組,記錄每一個字母出現的次數。而後根據這個記錄,從新打印(構造)出來排序後的字符串]

  1. 已知一個亂序的整數數組,求該數組排序相鄰兩數的最大間隔,要求時間複雜度爲O(n)

例如:給定數組爲10 23 7 1 35 27 50 41

排序後的結果爲:1 7 10 23 27 35 41 50

相鄰兩數的最大間隔爲13(10-23)。

遍歷找到數列找到最大最小值(max,min),則所求的gap>=(max-min)/n,以(max-min)/n爲步長創建k個桶,每一個桶記錄落入桶內的最大最小值,順序比較各個桶之間的最大gap。

答:

用基於桶排序的方式,具體以下:

先找到最小和最大,分別記爲min和max,並設avg=(max-min)/n

按照avg的大小將[min,max]分配(N-1)個桶

將數組中的數存入桶中

而後按順序對每一個相鄰桶(跳過沒有數的桶)進行比較,如相鄰桶(a, b)(c, d)的距離D=c-b

最終比較D的最大值,則爲所求

  1. 求兩個相同大小已排序數組的中位數

題目:設a[0..n-1]和b[0..n-1]是兩個已經排好序的數組,設計一個算法,找出a和b的2n個數的中位數。要求給出算法複雜度(O(lgn))。

答:

設a[0..n-1]的中位數是m1,b[0..n-1]的中位數爲m2

若是m1=m2,則m1則爲2n個數的中位數

若是m1>m2,則2n個數的中位數必定在a[0..2/n]和b[n/2..n],在求這兩個子數組的中位數

若是 m1<m2,則2n個數的中位數必定在a[n/2..n]和b[0..2/n],在求這兩個子數組的中位數

  1. 已知一個數組a1, a2, ..., an, b1, b2, ..., bn,設計一個算法把數組變成a1, b1, a2, b2, ..., an, bn

答:

若是 n = 2k,   則 C(k) =

若是 n = 2k+1, 則 C(k) =

ZhaiYao: 綜合考慮時間和空間。時間O(n)應該沒辦法下降了,以爲空間能夠達到是O(1)。可是沒想出來算法,【標記】

  1. 全排序算法

全排序算法就是列舉一些字符的全部排列順序。

void Perm(char list[], int k, int m)

{ //生成list [km ]的全部排列方式

  int i;

  if (k == m) {//輸出一個排列方式

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

      putchar(list[i]);

    putchar('\n');

  }

  else // list[km ]有多個排列方式

    // 遞歸地產生這些排列方式

    for (i=k; i <= m; i++) {

      Swap (&list[k], &list[i]);

      Perm (list, k+1, m);

      Swap (&list [k], &list [i]);

    }

}


Chap4 設計題[標記]

  1. 多線程鎖機制設計

在多線程編程中,對臨界資源,常常須要lock(),unlock()這樣的操做,可是常常在lock以後忘記unlock,形成多線程問題。如今用C++類的思想實現一個scopelock類(校招)

例如:

{

lock()

……

unlock()

}

這種使用模式變成

{

Scopelock()

}

(在構造函數和虛構函數中實現lock和unlock)

  1. 設計Spider

題目:Spider抓取能力一天10w個url,互聯網天天新增1000w個url  (社招)

這1000w個都是新增的url,spider怎麼選取10w個進行抓取,選優的準則

這1000w個有些是抓取過的,存在歷史抓取信息,spider怎麼選取10w個進行抓取,選優的準則。

  1. 海量url除重(spilt&merge的思想,主要看候選人的思路,2面)

答:

在獲取URL的時候按照必定數量分組,而後分別在每組用URL的sign做爲key,用awk以key爲標來構造數組;最後把每組過濾過的結果在merge起來過濾。

  1. 給定一個file,包含各種url,統計出現次數topNurl

答: sort|uniq -c|sort -nr|head

  1. 多路數組交集

題目:有十路數組,數組元素組成爲:{int id, unsigned int weight},每路數組內id、weight均爲無序

 要求:如何求出這十路數組的交集(交集:id相同),並將交集內的元素按照weight排序?給出思路和複雜度;若是原始的十路數組中的id均爲有序的,又該如何作?給出思路和複雜度;

  1. 兄弟單詞索引

題目:dog和god這類字母出現的次數和種類都徹底同樣的字符串稱爲兄弟單詞,如今有海量的字符串,設計檢索系統,支持查找用戶輸入字符串的全部兄弟單詞。

  1. 死鏈監測設計

題目:互聯網上天天有大量的網頁成爲死鏈,如何用最小的代價下降搜索引擎的死鏈率。

(考察其工程思惟能力,包括相關死鏈反饋、用戶點擊檢查、利用插件數據、站點穩定性等等)

  1. 用戶常常會輸錯query,如何糾錯

參考答案:發散問題,常見輸入法錯誤、缺字多字編輯距離判斷,用戶session挖掘等等


Chap5 邏輯題

  1. 一天,harlan的店裏來了一位顧客,挑了25元的貨,顧客拿出100元,harlan沒零錢找不開,就到隔壁飛白的店裏把這100元換成零錢,回來給 顧客找了75元零錢。過一會,飛白來找harlan,說剛纔的是假錢,harlan立刻給飛白換了張真錢,問harlan賠了多少錢(低)?

答:

方法A:

  • 列出每筆交易的收入和支出,給分
  • 答出結果,陪100元,給分

方法B:

  • 直接從結果出發,若是沒有假錢,不賺不虧,給分
  • 因爲收入100假錢,賠100,給分
  1. 5只貓5分鐘捉5只老鼠的速度計算,要在100分鐘內捉100只老鼠,須要多少隻貓(低)

答:5只貓

方法A:

  • 算出每隻貓每分鐘的捉鼠能力,給分
  • 算出答案,給分

方法B:

  • 把5只貓看爲總體,總體每分鐘的捉鼠能力,給分
  • 算出答案,給分
  1. 一副撲克牌54張,紅黑各一半,從裏面任意翻兩張,一紅一黑的可能性是多少(低)

答:27/53

  1. 一隻手錶100元買進,110元賣出;120元又買進,130元再賣出,問共賺了多少錢(低)

答:賺20元

  1. 有一牧場,已知養牛27頭,6天把草吃盡;養牛23頭,9天把草吃盡。若是養牛21頭,那麼幾天能把牧場上的草吃盡呢?而且牧場上的草是不斷生長的(中)

答:12天

1. 列出2個已知方程和一個求解方程,給分

2. 算出答案,給分 假設牧場的草爲1單位,天天生長x單位,每一個牛天天吃y單位

27y*6-6x=1

23y*9-9x=1

解得:y=1/72, x=15/72 [得一半分]

21頭牛,就是1/(21y-x)=12天 [得滿分]

  1. 4我的進入餐廳前都把本身的帽子交給寄存部的小姐保存。當他們一塊兒離開時粗心的小姐把那4頂帽子隨便的戴在每一個人的頭上。發完帽子之後你們發現沒有一我的 戴的本身的帽子。請問這種狀況發生的機率是多少?若是是n我的呢(n>1) (中)

答:

【4人時候,答案是9/24。9種可能分別是2143,4123,3142,3412,4312,2413,4321,3421,2341)】

【n人時候,解法以下】

 

解法1:

n人時候,運用容斥原理的高級形式求解。【想到容斥原理就給出一半分數】

 

lixin:這是全錯位排列問題http://baike.baidu.com/view/1926671.htm?fr=ala0_1

zhaiyao:本科的離散數學課程,本帽子題目是一個例題。我作助教的時候背熟了。。。

 

設人站成一排,第1個的帽子設爲帽子1,第i的人的帽子設爲帽子i。

 

設帽子i戴在人i的頭上(其餘人無所謂)的狀況數爲Ai

 

那麼很明顯有|Ai| =(n-1)! ;

i和j同時帶對(不考慮其餘人對不對)狀況是 |Ai ∩Aj| = (n-2)! ;

i和j,k同時帶對(不考慮其餘人對不對)|Ai ∩Aj ∩Ak | = (n-3)!

 

問題問沒有一我的帶對帽子,問題的反面就是問「存在至少一我的戴對帽子」

 

「存在至少一我的戴對帽子」的狀況數爲:|A1∪A2∪...∪An|

根據容斥原理,

|A1∪A2∪...∪An| =(|A1|+|A2|+…+|An|) - ( | A1 ∩A2| + | A1 ∩A3|  ) + (| A1 ∩A2 ∩A3| + )  - ….  (參見容斥原理)

= n*(n-1)! - C(n,2)*(n-2)! + C(n,3)*(n-3)! - ... + (-1)^(n-1)*C(n,n)*0!

=n!(1/1!-1/2!+...+(-1)^(n-1)*1/n!)

 

因此都帶錯的狀況是:

n!  -  n!(1/1!-1/2! + ...+(-1)^(n-1)*1/n!)

= n! *(1 - 1/1!+1/2!+...+(-1)^n* 1/n!)

 

機率是1 - 1/1!+1/2!-...+(-1)^(n-1)*1/n!

 = 1/2!-...+(-1)^(n-1)*1/n! 【獲得答案獲得所有分數】

 

 

形象點就是:

2我的: 1/2!

3我的:1/2! – 1/3!

4我的: 1/2! – 1/3! + 1/4!   (不是4/24,而是9/24。)

5我的: 1/2! – 1/3! + 1/4! – 1/5!

6我的: 1/2! – 1/3! + 1/4! – 1/5! +  1/6!

 

。。。

解法2:

人肉寫出n=2,3,4的狀況。而後進行數列規律解析,猜想出來最終表達式1/2!-...+(-1)^(n-1)*1/n!。

【若是隻能列出n=2,3,4等狀況,建議不給分,由於這個思路很容易想。

可是可以找到規律並猜想出表達式,建議給三分之二或者四分之三的分數。由於這個數列規律很很差找。可是這種思路必定不給滿分,由於沒有嚴格的推理過程】

  1. 甲、乙、丙每人出兩元共六元買了一個收音機,而後就一塊兒離開了商店,和他們一塊兒去的丁因有事沒有離開,這時售貨員發現收音機的售價應該是五元,就把那一元 錢退給了丁,丁回去時坐車花了4角,而後把剩下的6角分給了甲、乙、丙三人各2角,這時算賬甲、乙、丙每人花了1.8元,加上丁坐車花的4角,是5.8 元,那剩下的兩角錢哪兒去了(中)

答:

甲乙丙每人花了1.8元,但丁坐車沒有花4角(丁本身沒有錢),甲乙丙花的錢裏面,已經包含了丁的錢

這題沒法根據中間過程給分,不推薦

【ZhaiYao:這題有點混淆概念,能夠看出來一我的在混亂時候腦子能不能反應過來,分析清楚各類關係。解釋清楚就得滿分,不然不得分】

  1. 82的矩形中,填入後兩種圖形,一共有幾種填法(中)

 

答:34

1. 根據第2塊圖形填入的個數分類討論(或其餘方式分類討論),給分

2. 回答對答案,給分

[追問:對2*n的狀況,有多少種?遞推關係:n=1或者2,有1種;不然,f(n)=f(n-1)+f(n-2),斐波拉契數列]

  1. 村子裏有50我的,每人有一條狗。在這50條狗中有病狗(這種病不會傳染)。因而人們就要找出病狗。每一個人能夠觀察其餘的49條狗,以判斷它們是否生病, 只有本身的狗不能看。觀察後獲得的結果不得交流,也不能通知病狗的主人。主人一旦推算出本身家的是病狗就要槍斃本身的狗,並且每一個人只有權利槍斃本身的 狗,沒有權利打死其餘人的狗。第一天,次日都沒有槍響。到了第三天傳來一陣槍聲,問有幾條病狗,如何推算得出(中)

答:3條

1. 從1條病狗的狀況開始分析,給三分之一的分

2. 推廣到3條病狗,給滿分(須要解釋,直接說3條,卻解釋不清楚的,不得分)

[追問:若是第x天傳來一陣槍聲,那麼問一共有幾條病狗?這天響了多少槍?]

因爲題目的知名度較高,若是面試者很快答對,考慮不予計分

  1. 5只猴子在海邊發現一堆桃子,決定次日來平分。次日清晨,第一隻猴子最先來到,它左分右分分不開,就朝海里扔了一隻,剛好能夠分紅5份,它拿上本身 的一份走了。第 2345只猴子也遇到一樣的問題,採用了一樣的方法,都是扔掉一隻後,剛好能夠分紅5份。問這堆桃子至少有多少隻

答:3121

1. 從最後一隻猴子開始考慮,給分

2. 設最後一隻猴子來的時候,桃子的數量爲5x+1;第4只就爲(5x+1) * (5/4) + 1,給分

3. 依次類推,獲得第一隻猴子來的時候,桃子的數量,給分

4. 算出x的值,給分

[張一]: 用遞歸的方式來作,很巧妙!設f(n)爲第n次每隻猴子的份數。則4f(n) = 5f(n+1) + 1

1. 給出遞歸式,給分

2. 化爲等比數列,給分 f(n)=a*(4/5)^n-1。

2. 算出答案,

F(5)有意義,a最少爲5^5,因此f(1)=5^4 * 4 – 1 =624,總數爲624*5+1=3121

給分

  1. 有三我的都不能說話,但都很聰明。他們每人戴一頂帽子,帽子不是黑色就是紅色。這三人都苦思苦想,但願知道本身帽子的顏色,但終始終沒法得知。有一天,一個外地人見到這三人,隨口說了一句話:大家三人至少有一個是戴着紅帽子。說完就走了。當天三人聽完這句話,都紛紛回家苦思。第二 天中午,三人依舊一塊兒在廣場見面,有兩人立即宣佈了本身帽子的顏色。隨後,第三我的也知道了本身帽子的顏色。請問:這三人的帽子分別爲何顏色

答:

1. 若是隻有一頂紅帽子,則紅帽子的人當場就知道了,排除。給分

2. 若是三頂都是紅帽子,則無人能知道本身的顏色,由於他看到的另兩頂都是紅帽子。能夠排除。給分

3. 只能是2頂紅帽子,1頂黑帽子。思路以下:A黒,BC紅。3人都沒法肯定,回家苦思。B想:若是本身頭上黒帽,則C當即知道頭上是紅帽,既然C不知道,則說明本身頭上也是紅帽。次日猜出本身的帽子。C也是這樣。A根據BC的表現,知道只有2頂紅帽,本身頭上是黒帽。給分。

面試者解釋比較繁瑣,不推薦。

【ZhaiYao: 該題目面試者有自信的說出答案就能夠給分,不須要面試者詳細解釋】

  1. A,B兩人射箭,命中率都是50%。兩人比賽射箭,各射50箭,射中靶子多的人獲勝。比賽中A耍賴,多射了1箭,問A有多大的可能性獲勝。

答:

1. 將比賽結果分爲勝、平、負三種。給分

2. 各射50箭時,三種結果的可能性爲x, y, x;且x+y+x=100%。給分

3. A多射1箭,則原來獲勝時,如今仍是獲勝;原來打平時,如今50%可能獲勝;原來輸時,如今不可能獲勝。所以獲勝的可能性爲x+0.5y,正好等於50%。給分

注:若是面試者能以各射0箭,各射1箭等簡單狀況,推算出結果和本來的箭數無關,固定爲50%,能夠考慮給分。

  1. 假設一個國家沒有離婚、死亡等狀況出現。該國國王規定:一對夫妻的第一胎是男孩時候,不容許再生育;第一胎是女孩時候,夫妻能夠選擇生第二胎,也能夠不生;第二胎是女孩子的時候,還能夠繼續生。可是一旦生育了一個男孩,那麼就嚴禁再生育。當這個政策運行足夠久以後,該國的男女孩子的比例是多少?

答:

解法1:假設一共生育x孩子。那麼每次生育並不被其餘事件所影響,因此男女孩子各半。1:1

解法2:數學建模。

解法3:設想極端狀況:(1)你們都堅持只生一胎;(2)你們都一直生育,直到獲得男孩爲止;結論均爲50%。因此推出通常狀況下,也爲50%

注:若是面試者能以各射0箭,各射1箭等簡單狀況,推算出結果和本來的箭數無關,固定爲50%,能夠考慮給分。


Chap6編程及代碼題

  1. Strcpy函數的實現。(校招)

答:

1 char * strcpy(char * strDest,const char * strSrc){

if ((strDest==NULL)||(strSrc==NULL)) //[1]

throw "Invalid argument(s)"; //[2]

         char * strDestCopy=strDest;  //[3]

while ((*strDest++=*strSrc++)!='\0'); //[4]

return strDestCopy;

     }

2. 爲了實現鏈式返回

  1. Bigint乘法實現(bigint用數組存儲每個位) 社招

題目:void multiple(int a[], int b[], int c[]); //a,b爲兩個乘數,c爲輸出結果

考察點:就是編程實現一下小學的乘法運算,關注a,b各位相乘結果寫入c時,對應的下標運算,以及進位的處理。

若是寫的比較快,再考察一下怎麼測本身的代碼

答:

void multiply(int a[], int b[], int c[]) {

int i, j, k;  

      int tmp;  

      for (i = 0; i < a.size(); ++i) {  

         k = i;  

         for (j = 0; j < b.size(); ++j) {

             result[k++] += a[i] * b[j];  

         }

     }

     for (k = c.size() - 1;  k >= 0; --k) {  

         if (result[k] > 9) {

             if (k != 0){

                 c[k-1] += c[k] / 10;  

                 c[k] %= 10;  

             }else{

                 tmp = result[k] / 10;  

                 result[k] %=10;  

                 result.insert(result.begin(), tmp);  

             }

         }

    }

}

  1. 實現char *strtok(char *s, const char *delim);

題目:The strtok() function can be used to parse the string s into tokens. The first call to strtok() should  have  s  as its first argument. Subsequent calls should have the first argument set to NULL. Each call returns a pointer to the next token, or NULL when no more tokens are found.

答:

char *mystrtok(char *s,const char *delim)

{

    static char *last;

    char *tok;

    char *ucdelim;

    char *spanp;

    int c,sc;

    /**//*s爲空,而且上次剩餘值也爲空,則直接返回 NULL,不然slast或當前值中有值的一方*/

    if (s == NULL && (s = last) == NULL)

        return NULL;

    

    int found = 0;//是否找到與delim匹配的字符

    

    //處理連續的待匹配的字符

    cont:

    c=*s++;

    for (spanp = (char *)delim;(sc = *spanp++) != 0;)

    {

        if (c == sc)

            goto cont;

    }

    if (c == 0)

    {

        last = NULL;

        return NULL;

    }

    tok = s-1;

    while (!found && *s != '\0')

    {

        ucdelim = (char *) delim;

        while (*ucdelim)

        {

            if (*s == *ucdelim)

            {

                found = 1;

                *s = '\0';

                last = s + 1;

                break;

            }

            ucdelim++;

        }

        if (!found)

        {

            s++;

            if(*s=='\0')

                last = NULL;

        }

    }

    return tok;

}

  1. struct { int a, char b, long c} sizeof結果是多少,32位機器和64位機器下

答:32bit下12; 64bit下16

  1. int a = (int)(char)(byte)-1; a的值爲?  (位數補齊)

答:byte ó unsigned char => a = -1;

  1. aoti()的實現:

要求:

  • 不使用庫函數,實現int atoi(char *s)函數;
  • 在此基礎上,實現自定義的atoi()升級版,要求:
  • int atoi(char *s, unsigned int base)中,2<=base<=16,s是以進製爲base表示形式的字符串,好比:base=8時,」123」表示數字83。
  • 對以上代碼進行測試。

考察點:

  • 寫代碼能力,異常處理是否全面。
  • 主要考慮點:
  • NULL指針輸入;
  • atoi()在檢測到錯誤時,沒法return合適的值來表示這個錯誤;
  • 輸入字符串前綴的合法性檢查,
  • 字符串中的字符是否在當前進制能表示的範圍內,例如:字符’F’不在進製爲15的數字表示範圍內。

答:

  1. int atoi(char *s){

int c; // current char

int result;

int sign; // if '-', negative; otherwise positive;

/*skip the whitespace*/

while( isspace(*s) )

       s++;

sign = ( *s == '-' ) ? -1 : 1;

if( *s == '+' || *s == '-' ) //skip the sign

s++;

result = 0;

  while(isdigit(*s)){

result = 10 * result + ( *s - '0' );

s++;

}

return sign * result;

}

  1. result = 10 * result + ( *s - '0' ); 替換爲:result = base * result + (*s – ‘0’)便可
  2. strstr()的實現;

char *strstr(const char *s, const char *find){

        char *cp = s;

        char *s1;

        char *s2;

        /*find="\0"*/

        if(!*find)

               return s;

        while(*cp){

                s1 = cp;

                s2 = find;

                while(*s1 && *s2 && !(*s1 - *s2)){

                        s1++;

                        s2++;

                }

                if(!*s2)

                        return cp;

                cp++;

        }

        return NULL;

}

  1. 給出單向鏈表的定義,並實現以下操做:
  • add():在head增長一個節點;
  • delete():刪除指定的節點
  • retrieve():對全部節點進行「指定的函數操做」,「指定的函數操做」由用戶輸入;

考察點:

  • 單向鏈表的定義;
  • 功能代碼的實現;函數指針的運用(retrieve()中)。

答:

單向鏈表(單鏈表)是鏈表的一種,其特色是鏈表的連接方向是單向的,對鏈表的訪問要經過順序讀取從頭部開始。

1. Node定義:

typedef struct Node{

  DataType data;

  struct node *next;

}node;

2. add():在head增長一個節點

int add(Node *head, DataType DataX){

 //返回參數:0分配空間失敗,1成功

Node NodeAdd=new LinkList;

if(!NodeAdd)

return (0);

NodeAdd->data=DataX;

NodeAdd->Next=head->Next;

head->Next=NodeAdd;

return (1);

}

3. delete():刪除指定節點

int delete(Node *head, DataType DataX){

   Node *p = head;

   Node *s = p->next;

   while(s != NULL){

      if(s->data != Datax){

           p = p->next;

           s = s->next;

      }

      else{

          p -> next = s -> next;

          free(s);

          return 1;

      }

   }

  return 0;

}

4. retrieve():對全部節點進行「指定的函數操做」,「指定的函數操做」由用戶輸入;

void retrieve(Node *head, void (*visit)(data)){

Node *p = head;

while(p != NULL){

   (*visit)(p->data);

   p = p->next;

}

}

 

  1. 請找出下面代碼中的所錯誤

  說明:如下代碼是把一個字符串倒序,如「abcd」倒序後變爲「dcba」

一、#include"string.h"

  二、main()

  三、{

  四、 char*src="hello,world";

  五、 char* dest=NULL;

  六、 int len=strlen(src);

  七、 dest=(char*)malloc(len);  // 分配len+1

  八、 char* d=dest;

  九、 char* s=src[len];   //len-1

  十、 while(len--!=0)

  十一、 d++=s--;

  十二、 printf("%s",dest);  //尾部要加\0

  1三、 return 0;  //返回前要釋放malloc的內存

  1四、}

  1. 兩路歸併

void Merge(int *p1, unsigned uCount1, int *p2, unsigned uCount2)

{

    if (p1 == NULL || p2 == NULL || uCount1 == 0 || uCount2 == 0)

    {

        return;

    }

    int i = 0;

    int j = 0;

    bool fSign = false;

 

    while ((i < uCount1) && (j < uCount2))

    {

        if (p1[i] == p2[j])

        {

            if (!fSign)

            {

                printf("%d\n", p1[i]);

                fSign = true;

            }

            ++i;

        }

        else if (p1[i] < p2[j])

        {

            fSign = false;

            ++i;

        }

        else

        {

            fSign = false;

            ++j;

        }

    }

}

 

  1. 如下代碼會是什麼效果?

char str[]=」hello」;

int *p=(int *)str;

*p=0x00313200;

printf("%s",str);

//提示0x31對應字符'1',0x32對應字符'2'

答:返回空。」\0」

  1. 下列三個函數有沒有問題,若是有請指出:

void test1()

{

 char string[10];

 char* str1 = "0123456789";

 strcpy( string, str1 );

}  

 

void test2()

{

 char string[10], str1[10];

 int i;

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

 {

  str1[i] = 'a';

 }

 strcpy( string, str1 );

}  

 

void test3(char* str1)

{

 char string[10];

 if( strlen( str1 ) <= 10 )

 {

  strcpy( string, str1 );

 }

}  

答:

試題1字符串str1須要11個字節才能存放下(包括末尾的’\0’),而string只有10個字節的空間,strcpy會致使數組越界;

試題2,若是面試者指出字符數組str1不能在數組內結束能夠給3分;若是面試者指出strcpy(string, str1)調用使得從 str1內存起復制到string內存起所複製的字節數具備不肯定性能夠給7分,在此基礎上指出庫函數strcpy工做方式的給10分;

對試題3,if(strlen(str1) <= 10)應改成if(strlen(str1) < 10),由於strlen的結果未統計’\0’所佔用的1個字節。

  1. 說明如下函數所實現的功能以及可能存在的問題:

int function(char *s1, char *s2)

{

int i=0;

while(s1[i]==s2[i] && s2[i]!=0 ) i++;

return (s1[i]==0 && s2[i]==0);

}

答:

功能——判斷s2與s1是否內容一致

問題——沒有判斷參數爲NULL的狀況;當s1==s2的時候,函數應該直接返回true,不須要一個個去比較下去;

  1. 如下程序的輸出是怎樣的?請給出分析過程。

class myclass

{

 public:

  //Constructor

  myclass( string s ):str(s)

  {

   cout << "Constructing " << endl ;

  }

  

  //Destructor

  ~myclass()

  {

   cout << "Destructing " << endl ;

  }

  

  string getValue()

  {

   return str ;

  }

 

 private:

  string str ;

} ;

 

void display( myclass t )

{

 cout << t.getValue() << endl ;

}

 

myclass getTest()

{

 return myclass("Jun") ;

}

 

int main()

{

 myclass te = myclass("chenjq") ;

 display(te) ;

 getTest() ;

 return 0;

}

答:

輸出:

Constructing

chenjq

Destructing

Constructing

Destructing

Destructing

重點:須要瞭解在按值傳向函數,以及按值從函數返回的時候對象的構造、析構過程:

(1) 將對象按值傳給函數的時候,首先會建立該對象的一個副本,將這個副本傳給函數,可是在建立這個副本的時候,不會調用構造函數,而在這個函數返回的時候會調用析構函數。

(2) 函數按值返回對象的時候,也會建立返回對象的一個副本,一樣的也不會調用構造函數,在返回後調用析構函數銷燬該對象。

  1. 解釋如下代碼中函數function()的執行過程,指出可能存在的問題:

class myclass{

public:

 myclass(unsigned int k):length(k){

content=(int *)malloc(sizeof(int)*k);

}

 

~myclass(){

if(content)free(content);

}

private:

 unsigned int length;

 int *content;

}

 

void function()

{

myclass c1=100;

myclass c2=c1;

myclass c3;

 

myclass c4=200;

c4=c1;

 

}

答:

  • myclass c1=100; 調用constructor myclass(unsigned int k),其中伴隨automatic type conversion;爲c1.content指針分配了內存。
  • myclass c2=c1; 調用默認的copy constructor,採用member-wize的copy,致使c2的content指針指向c1. Content指向的區域;
  • myclass c3; 這裏須要調用default constructor,可是因爲本身定義了其餘類型的constructor,編譯器不會在自動幫助生成default constructor,編譯不經過;
  • c4=c1; 調用copy assignment operator,實施member-wize的copy,致使c4的content指針也指向c1. Content指向的區域;構造函數爲c4分配的內存成爲孤立區域,致使內存泄露。
  • 函數退出,噩夢開始:不考慮c3的話,這裏共調用constructor myclass(unsigned int k)兩次,可是卻要調用destructor三次。因爲指針淺copy,三次destructor會對同一塊內存free三次,這是個問題。
  1. 解釋如下代碼中函數function()的執行過程,指出可能存在的問題:

class myclass{

public:

myclass(unsigned int k):length(k){

content=(int *)malloc(sizeof(int)*k);

 

}

 

~myclass(){

if(content)free(content);

}

private:

unsigned int length;

int *content;

 

}

 

void function()

{

void *p=new myclass(100);

delete p;

}

答:

Delete操做,因爲p是void *類型,在free對象自己所佔的內存空間以前,不會調用destructor,帶形成content指針指向的內存區域的泄露。

  1. 請寫出如下程序的運行結果,並解釋致使這樣運行結果的關鍵性緣由。

 #include <iostream>

using std::cout;

class P

{

public:

virtual void print()

{

cout << "P";

}

};

class Q: public P

{

public:

virtual void print()

{

cout << "Q";

}

};

int main()

{

P * p = new P;

Q * q = static_cast <Q *> (p);

 

q->print();

delete p;

cout << endl;

 

q = new Q;

p = q;

q->print();

p->print();

cout << endl;

 

p = new (q) P;

q->print();

p->print();

cout << endl;

 

p->~P();

delete q;

return 0;

}

答:輸出爲 —— P QQ PP


Chap7 計算機基礎

  1. C/C++[標記]
  • Inline函數、虛函數的概念;虛函數是否能夠實現成inline

inline 函數:

定義:

關鍵字用來定義一個類的內聯函數,函數的代碼被放入符號表中,在使用時直接進行替換,(像宏同樣展開),沒有了調用的開銷,效率也很高。

用途:

引入它的主要緣由是用它替代C中表達式形式的宏定義。

虛函數:

定義:

在某基類中聲明爲virtual並在一個或多個派生類中被從新定義的成員函數。

用途:

實現多態性,經過指向派生類的基類指針,訪問派生類中同名覆蓋成員函數。

虛函數是否能夠實現成inline?

從狹義的角度來說是不能的,由於虛函數是在運行期間決定如何調用,而inline函數實在編譯期間決定是否inline。從廣義的角度講是能夠的。參見《More Exceptional C++》第8條款,《Exceptional C++ Style》第25條款。

  • 函數調用過程當中,函數參數的入棧順序,why?

函數調用過程當中,第一個進棧的是(主函數中的)調用處的下一條指令(即函數調用語句的下一條可執行語句)的地址;而後是函數的各個參數,而在大多數C/C++編譯器中,在函數調用的過程當中,函數的參數是由右向左入棧的;而後是函數內部的局部變量(注意static變量是不入棧的);在函數調用結束(函數運行結束)後,局部變量最早出棧,而後是參數,最後棧頂指針指向最開始存的指令地址,程序由該點繼續運行。

函數調用方式決定了函數參數入棧的順序,是由調用者函數仍是被調用函數負責清除棧中的參數等問題,而函數名修飾規則決定了編譯器使用何種名字修飾方式來區分不一樣的函數,若是函數之間的調用約定不匹配或者名字修飾不匹配就會產生以上的問題。

參考:http://caifuchang.blog.163.com/blog/static/33912331201041611260151/

  • extern的使用場合以及工做原理

extern 能夠用引用頭文件的方式,也能夠用extern關鍵字,若是用引用頭文件方式來引用某個在頭文件中聲明的全局變理,假定你將那個編寫錯了,那麼在編譯期間會報錯,若是你用extern方式引用時,假定你犯了一樣的錯誤,那麼在編譯期間不會報錯,而在鏈接期間報錯。

C++語言支持函數重載,C 語言不支持函數重載。函數被C++編譯後在庫中的名字與C 語言的不一樣。假設某個函數的原型爲: void foo(int x, int y);該函數被C 編譯器編譯後在庫中的名字爲_foo , 而C++ 編譯器則會產生像_foo_int_int 之類的名字。C++提供了C 鏈接交換指定符號extern「C」來解決名字匹配問題。 

  • C++中 struct和class的區別

C++的class具備數據封裝功能,其包含屬性訪問級別能夠爲private,public和protect,還具備實現類接口功能和輔助功能的操做函數,而struct屬性訪問權限只有public,沒有數據封裝功能,也就沒有實現信息隱藏這一面向對象的思想的機制,struct自己不含有操做函數,只有數據。

  • OO語言中動態綁定的概念。參考答案網上都有考察精通c++/java的面試者對基本概念的瞭解

靜態綁定:編譯時綁定,經過對象調用

動態綁定:運行時綁定,經過地址實現

只有採用「指針->函數()」或「引用變量.函數()」的方式調用C++類中的虛函數纔會執行動態綁定。對於C++中的非虛函數,由於其不具有動態綁定的特徵,因此無論採用什麼樣的方式調用,都不會執行動態綁定。

  • C++中多態的概念及實現機制(答題點:虛函數,虛表)

多態(Polymorphism)是面向對象的核心概念, C++中多態能夠分爲基於繼承和虛函數的動態多態以及基於模板的靜態多態, 

1) 描述如下表示形式的意義:Char *q[]={「xxx」, 「yyy」, 「zzz」};

Char (*p)[]=a;

答:

前者:指針數組,q[0],q[1],q[2]都爲char *類型的指針;

後者:數組指針,p指向一個char數組。

2) 解釋如下表示形式的意義:

A) "a"    B) '\\'    C) 'W'    D) ’abc’

3) 解釋如下表示形式的意義及其做用:typedef int (*PFUN)(int x,int y);

答案:函數指針;

4) Call by value、call by reference和call by pointer的優缺點,舉例說明各自的應用形式。

 

5) C++對象的copy constructor與copy assignment的區別與聯繫,談談使用時的注意事項,列舉它們應用的場景及。

答:

copy constructor:從一個已有的對象來構造另外一個對象;包括:

用已有對象來初始化新聲明的對象;

將對象按值傳遞給函數做爲參數;

函數按值返回對象。

copy assignment:將已有的對象賦值個另外一個已有的對象;

實例:

Person A(B); // copy constructor

Person C=B; //copy constructor

Function1(D); //copy constructor

B= Function2(…); //copy constructor

Person D;

D=B; //copy assignment

注意事項:編譯器默認的copy constructor和copy assignment操做,是按照member-wise copy的方式逐個copy每一個member,這種淺拷貝操做在有些狀況下可能形成資源泄漏/指向重疊。

若是的確須要deep copy,須要自定義相應操做。這時須要清楚哪些地方用了copy constructor,哪些地方用了copy assignment,從而分別自定義copy constructor和copy assignment。通常來講,自定義的copy constructor、destructor和copy assignment操做經常同時出現。

區別與聯繫:

copy constructor不用檢測是不是用一個對象來初始化它本身;

copy constructor不用對被構造對象作資源清理操做,如delete操做;

6) 說明如下表達式的意義:TYPE *t = new(a) TYPETYPE;

答: Placement new操做:在a指向的內存區域,調用default constructor構造一個TYPE類型的對象,並返回該對象的指針。

7) 解釋如下表達式的區別:TYPE t TYPE *PT=new TYPE;

答: TYPE t; 從static area或者stack上分配內存,並調用default constructor;

TYPE *PT=new TYPE; 從堆上分配內存,並調用default constructor;

  1. JAVA

1) Java多線程編程機制,線程類,互斥機制(synchronize) Java線程類:Thread,Runnable接口 Java互斥:synchronize關鍵字 wait和notify方法

答:

  • 繼承和實現的區別。當一個類已經繼承了其餘類,就不能繼承Thread,只能實現runnable。
  • 每一個JAVA對象都有一把所,當有多個線程同時訪問共享資源的時候,須要Synchronize 來控制安全性,synchronize分synchronize 方法和synchronize塊,使用synchronize塊時, 必定要顯示的得到該對象的鎖(如synchronize(object))而方法則不須要
  • 在java多線程編程中,最被常常用到的即是wait與notfiy方法,這兩個方法能夠用來更加精確地控制被同步的代碼,從而使得被同步的代碼最小化,提升併發效率。當某個類的某個方法被標記爲synchronized時,這個方法在同一時間只能被一個線程訪問。此時這個方法中的全部代碼都是被同步的,只有當一個線程執行完全部的代碼以後,下一個線程才能開始執行。當被同步的方法代碼量比較小,並且每一步執行都很是快的時候僅僅使用synchronized關鍵字就夠了。

可是,若是被同步的方法裏面有一些代碼是能夠被共享的,並且這些可以被共享的代碼裏面存在比較耗時的操做時,僅僅使用synchronized關鍵字就沒法達到最高的效率,這個時候能夠使用wait與notify方法來對併發訪問作更進一步的控制。

wait()方法表示,放棄當前對資源的佔有權,等啊等啊,一直等到有人通知我,我纔會運行後面的代碼。 notify()方法表示,當前的線程已經放棄對資源的佔有,通知等待的線程來得到對資源的佔有權,可是隻有一個線程可以從wait狀態中恢復,而後繼續運行wait()後面的語句;notifyAll()方法表示,當前的線程已經放棄對資源的佔有,通知全部的等待線程從wait()方法後的語句開始運行。

2) 引用傳遞 Java函數傳遞的是參數的引用 深度拷貝:重寫clone()

3) 接口和抽象類的做用有什麼區別

答:

接口可以多重繼承;抽象類只能繼承一個;

接口只能定義常量;抽象類可以定義變量

接口的函數都是抽象的;抽象類的函數能夠是非抽象的

接口implement,抽象extend

4) 重載和覆寫

答:

重載時function(int i), function(int i, int j)。相同的函數名,不一樣的簽名;重寫是函數簽名相同。可是子類的函數覆蓋了父類的同名(簽名)函數。

5) 容器類型選擇: ArrayList:隨機訪問好 LinkedList:元素添加和移出(中心位置) HashSet:廣泛性能都比TreeSet好 TreeSet:保持內部元素的排序狀態 HashMap:Hashtable的替代品,通常性能都較好 TreeMap:保持內部元素的排序狀態

6) 向上轉型和向下轉型 向上安全,向下執行期檢查:ClassCastException

7) 多態 繼承,接口與多態的關係

  1. 多線程:

1) 是否寫過多線程代碼

2) 線程間通訊的方法

答:同一進程的各線程能夠直接讀寫進程數據段進行通訊,同時須要同步和互斥手段的輔助。而不一樣進程間的線程通訊能夠參考不一樣進程間的通訊。

3) 多線程同步方式(能答出幾個就能夠)

答:事件Event, 臨界區域Critical Section, 互斥器Mutex,  信號量Semaphore

詳細參考:http://baike.baidu.com/view/2808915.htm

4) 同步和異步的區別

答:同步是阻塞模式,即發送方發出數據後,等接收方發回響應之後才發下一個數據包的通信方式;而異步是非阻塞方式,發送方發出數據後,不等接收方發回響應,接着發送下個數據包的通信方式。

例如:普通B/S模式(同步)AJAX技術(異步)

同步:提交請求->等待服務器處理->處理完畢返回 這個期間客戶端瀏覽器不能幹任何事

異步: 請求經過事件觸發->服務器處理(這是瀏覽器仍然能夠做其餘事情)->處理完畢

5) 進程和線程的概念

答:進程是操做系統結構的基礎;是一個正在執行的程序;計算機中正在運行的程序實例;能夠分配給處理器並由處理器執行的一個實體;由單一順序的執行顯示,一個當前狀態和一組相關的系統資源所描述的活動單元。

線程(thread),有時被稱爲輕量級進程(Lightweight Process,LWP),是程序執行流的最小單元。一個標準的線程由線程ID,當前指令指針(PC),寄存器集合和堆棧組成。另外,線程是進程中的一個實體,是被系統獨立調度和分派的基本單位,線程本身不擁有系統資源,只擁有一點在運行中必不可少的資源,但它可與同屬一個進程的其它線程共享進程所擁有的所有資源。一個線程能夠建立和撤消另外一個線程,同一進程中的多個線程之間能夠併發執行。因爲線程之間的相互制約,導致線程在運行中呈現出間斷性。線程也有就緒、阻塞和運行三種基本狀態。

兩者區別:子進程和父進程有不一樣的代碼和數據空間,而多個線程則共享數據空間,每一個線程有本身的執行堆棧和程序計數器爲其執行上下文.多線程主要是爲了節約CPU時間,發揮利用,根據具體狀況而定. 線程的運行中須要使用計算機的內存資源和CPU。一般在一個進程中能夠包含若干個線程,它們能夠利用進程所擁有的資源。在引入線程的操做系統中,一般都是把進程做爲分配資源的基本單位,而把線程做爲獨立運行和獨立調度的基本單位。

6) 進程的地址空間是怎麼回事?虛擬內存是如何實現的

答:虛擬內存的存在使得CPU上的指令訪問的地址都是虛擬地址,而這些地址是須要在物理內存中真實存在的,這裏就須要在虛擬地址和物理地址直接創建一個映射關係(應當是多對一的關係),說白了就是一個整數集合到另外一個整數集合的映射。而後在查找時,根據相應的算法(如先進先出,最多使用等)進行調度。

7) Linux進程間通訊有哪些方式,優缺點如何

答: Linux下進程間通訊的幾種主要手段:

  • 管道(Pipe)及有名管道(named pipe):管道可用於具備親緣關係進程間的通訊,有名管道克服了管道沒有名字的限制,所以,除具備管道所具備的功能外,它還容許無親緣關係進程間的通訊;
  • 信號(Signal):信號是比較複雜的通訊方式,用於通知接受進程有某種事件發生,除了用於進程間通訊外,進程還能夠發送信號給進程自己;Linux除了支持Unix早期信號語義函數sigal外,還支持語義符合Posix.1標準的信號函數sigaction(實際上,該函數是基於 BSD的,BSD爲了實現可靠信號機制,又可以統一對外接口,用sigaction函數從新實現了signal函數);
  • 報文(Message)隊列(消息隊列):消息隊列是消息的連接表,包括Posix消息隊列systemV消息隊列。有足夠權限的進程能夠向隊列中添加消息,被賦予讀權限的進程則能夠讀走隊列中的消息。消息隊列克服了信號承載信息量少,管道只能承載無格式字節流以及緩衝區大小受限等缺點。
  • 共享內存:使得多個進程能夠訪問同一塊內存空間,是最快的可用IPC形式。是針對其餘通訊機制運行效率較低而設計的。每每與其它通訊機制,如信號量結合使用,來達到進程間的同步及互斥。
  • 信號量(semaphore):主要做爲進程間以及同一進程不一樣線程之間的同步手段。
  • 套接口(Socket):更爲通常的進程間通訊機制,可用於不一樣機器之間的進程間通訊。起初是由Unix系統的BSD分支開發出來的,但如今通常能夠移植到其它類Unix系統上:Linux和System V的變種都支持套接字。
  1. 網絡編程

1) Tcp/IP鏈接模型

答:TCP/IP 通信協議採用了四層的層級模型結構,每一層都調用它的下一層所提供的網絡任務來完成本身的需求:

應用層 (Application):應用層是個很普遍的概念,有一些基本相同的系統級 TCP/IP 應用以及應用協議,也有許多的企業商業應用和互聯網應用。

傳輸層 (Transport):傳輸層包括 UDP 和 TCP,UDP 幾乎不對報文進行檢查,而 TCP 提供傳輸保證。

網絡層 (Network):網絡層協議由一系列協議組成,包括 ICMP、IGMP、RIP、OSPF、IP(v4,v6) 等。

鏈路層 (Link):又稱爲物理數據網絡接口層,負責報文傳輸。

2) Io複用,select和poll的區別

答:IO複用模型:調用select或poll,在這兩個系統調用中的某一個上阻塞,而不是阻塞於真正I/O系統調用。 阻塞於select調用,等待數據報套接口可讀。當select返回套接口可讀條件時,調用recevfrom將數據報拷貝到應用緩衝區中。

select和poll的區別:select()和poll()本質上來說作的是同一件事,只是完成的方法不同。二者都經過檢驗一組文件描述符來檢測是否有特定的時間將在上面發生並在必定的時間內等待其發生。

select()函數的接口主要是創建在一種叫'fd_set'類型的基礎上。它('fd_set') 是一組文件描述符 (fd)的集合。

poll ()接受一個指向結構'struct pollfd'列表的指針,其中包括了你想測試的文件描述符和事件。事件由一個在結構中事件域的比特掩碼肯定。當前 的結構在調用後將被填寫並在事件發生後返回。

3) 實現一個client/server的通訊過程,寫一段僞代碼(重點寫出須要調用的各socket api)

答:

Server端:

socket addr_in svr_addr;

socket addr_in client_addr;

ServerSocket(addr_in_svr_addr);

bind();

listen();

while(true){

    client = accept(addr_in client_addr);

    if(!fork()){

read();

send(client);

close(client);

     }

}

Client :

 socket(addr_in_client_addr);

connect(server);

data = recv();

close();

4) TCP和UDP的區別,擁塞窗口的概念,如何創建一個TCP鏈接

答:TCP---傳輸控制協議,提供的是面向鏈接、可靠的字節流服務。當客戶和服務器彼此交換數據前,必須先在雙方之間創建一個TCP鏈接,以後才能傳輸數據。TCP提供超時重發,丟棄重複數據,檢驗數據,流量控制等功能,保證數據能從一端傳到另外一端。

UDP---用戶數據報協議,是一個簡單的面向數據報的運輸層協議。UDP不提供可靠性,它只是把應用程序傳給IP層的數據報發送出去,可是並不能保證它們能到達目的地。因爲UDP在傳輸數據報前不用在客戶和服務器之間創建一個鏈接,且沒有超時重發等機制,故而傳輸速度很快

擁塞窗口: 在TCP傳送中的擁塞控制中,發送端經過網絡的擁塞程度所給出的一個大小值,而這個值就是擁塞窗口。

創建TCP鏈接:TCP鏈接時經過三次握手創建的,詳細見下面所示。

5) Tcp鏈接創建的三次握手是指什麼

答:第一步是請求端(客戶端)發送一個包含SYN即同步(Synchronize)標誌的TCP報文,SYN同步報文會指明客戶端使用的端口以及TCP鏈接的初始序號;

第二步,服務器在收到客戶端的SYN報文後,將返回一個SYN+ACK的報文,表示客戶端的請求被接受,同時TCP序號被加一,ACK即確認(Acknowledgement)。

第三步,客戶端也返回一個確認報文ACK給服務器端,一樣TCP序列號被加一,到此一個TCP鏈接完成。而後纔開始通訊的第二步:數據處理。

TCP Client

Flags

TCP Server

1 Send SYN (seq=x)

----SYN--->

SYN Received

2 SYN/ACK Received

<---SYN/ACK----

Send SYN (seq=y)ACK (x+1)

3 Send ACK (y+1)

----ACK--->

ACK ReceivedConnection Established

TCP/IP協議中,TCP協議提供可靠的鏈接服務,採用三次握手創建一個鏈接。

第一次握手:創建鏈接時,客戶端發送syn(syn=j)到服務器,並進入SYN_SEND狀態,等待服務器確認;

第二次握手:服務器收到syn包,必須確認客戶的SYNack=j+1),同時本身也發送一個SYN包(syn=k),即SYN+ACK包,此時服務器進入SYN_RECV狀態;

第三次握手:客戶端收到服務器的SYNACK包,向服務器發送確認包ACK(ack=k+1),此包發送完畢,客戶端和服務器進入ESTABLISHED狀態,完成三次握手。

完成三次握手,客戶端與服務器開始傳送數據,

6) tcp鏈接的time_wait是什麼狀態,描述其發生的場景,說明它存在的好處/壞處

答:TCP包括一種機制, 確認與鏈接相關的包在網絡上延遲後不被同一對主機之間後來的鏈接所接受. 這種機制是由TCP 協議的T IM E_WA IT 狀態實現的. 當一端點關閉一個TCP 鏈接時, 它保留與鏈接有關的狀態—— 一般是TCB(TCP protocol control block) 的複製——兩倍於最大段存活時間(maximum segment life time, 即MSL ). 處於此狀態的鏈接即處於TIME_WAIT 狀態;

TIME_WAIT的優勢:可靠地實現TCP全雙工鏈接的終止;容許老的重複分節在網絡中消逝 。

TIME_WAIT的缺點:重負載服務器有可能保留有上千個TIME_WAIT TCB, 於是消耗了大量的內存並能減慢活動的鏈接。

  1. Linux

1) Shell命令,sed,awk等。

參考問題及答案:

Shell:

用沒用過shell命令。若是用過,說下經常使用的shell命令。

問下cat chmod diff more/less, paste, head/tail, uniq, sort, who

Sed:

Sed簡介參看翟耀的分享: http://com.baidu.com/twiki/bin/view/Sdc/SedEditorShare

考察這幾個命令的理解:

(1) sed '/line/ p' list.txt

(2) sed -n '/line/ p' list.txt

(3) sed '3q' new

(4)

$ sed -n -f holdtest list.txt

其中holdtest是個文本文件

$ cat holdtest

h

n

p

g

p

(***Only For面試官***

h #拿到一行line1而且複製到hold區。目前p區[line1],h區[line1]

n #取下一行line2放入p區。目前p區[line2],h區[line1]

p #打印p區內容:line2

g #把h區內容複製到p區。目前p區[line1],h區[line1]

p #打印p區內容:line1。這樣就作到了每兩行互相替換。)

Awk:

Awk簡介參看翟耀的分享: http://com.baidu.com/twiki/bin/view/Sdc/GawkShare

能夠考察以下題目:

gawk '/^f/' cars

gawk '$1 ~ /l/' cars

用gawk把全部行加上行長,並按照長度大小排序

gawk '{print length, $0}' cars | sort –n

2) 是否熟悉Linux下的C/C++開發,gcc,gdb,makefile等一些編譯,調試工具,是否熟悉。

3) 文件系統的組織結構,文件重定向是如何實現的

參考答案:ls -la /

下面咱們把Linux文件系統的樹形結構的主要目錄列一下

/ Linux文件系統的入口,也是處於最高一級的目錄;

/bin 基礎系統所須要的那些命令位於此目錄,也是最小系統所須要的命令;好比 ls、cp、mkdir等命令;功能和/usr/bin相似,這個目錄中的文件都是可執行的,普通用戶均可以使用的命令。作爲基礎系統所須要的最基礎的命令就是放在這裏。

/boot Linux文件系統的內核及引導系統程序所須要的文件,好比 vmlinuz initrd.img 文件都位於這個目錄中。在通常狀況下,GRUB或LILO系統引導管理器也位於這個目錄;

/dev 設備文件存儲目錄,好比聲卡、磁盤... ...

/etc 系統配置文件的所在地,一些服務器的配置文件也在這裏;好比用戶賬號及密碼配置文件;

/home 普通用戶家目錄默認存放目錄;

/lib 庫文件存放目錄

/mnt 這個目錄通常是用於存放掛載儲存設備的掛載目錄的,好比有cdrom 等目錄。

/root Linux文件系統超級權限用戶root的Home目錄;

 

考察管道,重定向等概念和使用。

重定向的分享見: http://com.baidu.com/twiki/bin/view/Sdc/OutputRedirection

重定向用着簡單,重要是思考重定向的實現方式。

能夠考下 ./myprog 1>tmp 2>tmp是否正確?應該怎麼改?

答案:./myprog 1>tmp 2>&1

  1. cookiesession的概念;二者的實現方式;二者的應用場景
  • cookie機制和session機制的區別

具體來講cookie機制採用的是在客戶端保持狀態的方案,而session機制採用的是在服務器端保持狀態的方案。

同時咱們也看到,因爲才服務器端保持狀態的方案在客戶端也須要保存一個標識,因此session

機制可能須要藉助於cookie機制來達到保存標識的目的。其實有其餘辦法。

session機制是一種服務器端的機制,服務器使用一種相似於散列表的結構(也可能就是使用散列表)來保存信息。但程序須要爲某個客戶端的請求建立一個session的時候,服務器首先檢查這個客戶端的請求裏是否包含了一個session標識-稱爲session id,若是已經包含一個session id則說明之前已經爲此客戶建立過session,服務器就按照session id把這個session檢索出來使用(若是檢索不到,可能會新建一個,這種狀況可能出如今服務端已經刪除了該用戶對應的session對象,但用戶人爲地在請求的URL後面附加上一個JSESSION的參數)。

若是客戶請求不包含session id,則爲此客戶建立一個session而且生成一個與此session相關聯的session id,這個session id將在本次響應中返回給客戶端保存。

cookie:將你的全部提供的這些信息和登錄信息,以文件的形式保存到你的計算機上,當訪問其餘文件的時候,首先把cookies提交給服務器,服務器判斷這裏的信息,得知你是什麼樣的一個用戶,而後給出你相應的功能頁面.能夠自行設置cookies的存在週期,除非設置了臨時cookies,不然關閉瀏覽器後cookies信息仍舊保存在主機的硬盤上。

session:將你所提供的信息,以犧牲服務器資源的方式記錄下來,當你訪問其餘頁面的時候,先判斷服務器上的關於你的信息,並提供給你相應的功能頁面.變量保存在客戶端主機的內存上,關閉瀏覽器或者session腳本過時後,即自動清除。

  • Cookies與Session的應用場景:

Cookies的安全性能一直是倍受爭議的。雖然Cookies是保存在本機上的,可是其信息的徹底可見性且易於本地編輯性,每每能夠引發不少的安全問題。因此Cookies到底該不應用,到底該怎樣用,就有了一個須要給定的底線。

先來看看,網站的敏感數據有哪些。

登錄驗證信息。通常採用Session("Logon")=true or false的形式。

用戶的各類私人信息,好比姓名等,某種狀況下,須要保存在Session裏

須要在頁面間傳遞的內容信息,好比調查工做須要分好幾步。每一步的信息都保存在Session裏,最後在統一更新到數據庫。

固然還會有不少,這裏列舉一些比較典型的

假如,一我的孤僻到不想碰Session,由於他認爲,若是用戶萬一不當心關閉了瀏覽器,那麼以前保存的數據就所有丟失了。因此,他出於好意,決定把這些用Session的地方,都改爲用Cookies來存儲,這徹底是可行的,且基本操做和用Session如出一轍。那麼,下面就針對以上的3個典型例子,作一個分析

很顯然,只要某個有意非法入侵者,知道該網站驗證登錄信息的Session變量是什麼,那麼他就能夠事先編輯好該Cookies,放入到Cookies目錄中,這樣就能夠順利經過驗證了。這是否是很可怕?

Cookies徹底是可見的,即便程序員設定了Cookies的生存週期(好比只在用戶會話有效期內有效),它也是不安全的。假設,用戶忘了關瀏覽器 或者一個惡意者硬性把用戶給打暈,那用戶的損失將是巨大的。

這點如上點同樣,很容易被它人竊取重要的私人信息。但,其還有一個問題所在是,可能這些數據信息量太大,而使得Cookies的文件大小劇增。這可不是用戶但願所看到的。

顯然,Cookies並非那麼一塊好啃的小甜餅。但,Cookies的存在,固然有其緣由。它給予程序員更多發揮編程才能的空間。因此,使用Cookies改有個底線。這個底線通常來講,遵循如下原則。

不要保存私人信息。

任何重要數據,最好經過加密形式來保存數據(最簡單的能夠用URLEncode,固然也能夠用完善的可逆加密方式,遺憾的是,最好不要用md5來加密)。

是否保存登錄信息,需有用戶自行選擇。

長於10K的數據,不要用到Cookies。

參考答案網上都有

考察項目多爲前端開發/測試的面試者對基本概念的瞭解


Chap 8 項目和背景

結合項目詢問對測試瞭解的狀況,談談對測試流程的理解:什麼階段介入測試比較好;對Code Review的見解,RD和QA各自的側重點;測試完成的衡量標準,是否接觸過測試覆蓋率;自動化的實現方法,談一下測web常見的一些自動化思路。。。


Chap9 外部工具

  1. Selenium

1) 介紹一下selenium? Selenium有哪些特色?

答: Selenium是一個針對Web應用的開源測試框架,它的測試用例能夠用HTML table和HTML代碼或者一些很是流行的編程序言進行開發,並且它能在幾乎全部如今的瀏覽器上執行。selenium能夠被部署到Windows, Linux和Macintosh平臺上。它支持的語言有Java, Python, Ruby, .Net, Perl等等

主要的特色:

l 支持錄製和回放

l 可以靈活的根據ID, Name或者XPath來進行頁面元素的選取

l 可以進行Debug和設置斷點

l 可以把測試腳本保存成HTML, Ruby或者其餘語言

l 支持user-extensions.js形式的用戶擴展

l 可以自動進行頁面的斷言

2) Selenium分爲哪幾部分?

Selenium IDE: 一個firefox插件,能夠錄製、回放測試腳本。

Selenium RC:支持用程序語言編寫測試用例,好比Ruby、Java、C#等,這樣作的好處是,能夠將Selenium和其餘測試框架集成,好比.NET環境下,能夠把 Selenium和NUnit集成,用Selenium來編寫測試用例,用NUnit來實現測試用例的自動化運行。

Selenium Core:Selenium Core是Selenium的核心,是由Javascript和Html文件組成的,它是Selenium IDE和Selenium RC的核心引擎。

Selenium Grid:Selenium Grid是Selenium的一個擴展,它能夠將一批selenium腳本分配到不一樣的測試機上面同步運行,從而節省執行時間。

3) Selenium中verifyTextPresent和assertTextPresent命令的區別?

答:verifyTestPresent和assertTextPresnt命令都用於判斷頁面上是否存在指定的文本,區別是verifyTestPresent結果是false時,剩餘的步驟會繼續執行。但assertTextPresent結果是false時直接終結該腳本剩餘步驟的運行。

4) Selenium中click和clickAndWait的區別?

答:click命令模擬用戶點擊的動做。命令執行完畢後馬上執行下一條命令。ClickAndWait命令在點擊後有一個等待的過程,會等頁面從新加載完畢再執行下一條命令。

5) 若是有一個按鈕,點擊該按鈕後會發出一個ajax call,而後獲得返回結果後將該內容顯示到新彈出的一個layer中。在寫腳本的時候,點擊按鈕這個動做是否能夠用clickAndWait命令?若是不行,怎麼解決?

答:不能使用clickAndWait。由於ajax call不會刷新頁面,clickandWait命令會由於等待頁面從新加載而出現Time out. 對這種狀況應該使用click命令結合pause命令。

6) 下面是某頁面中的一段html source,其中某a連接的地址中包含關鍵字test。用xpath定位該a元素。

<html>

......

<a href="http://www.baidu.com/s?wd=test">baidu</a>

......

</html>

答: //a[contains(@href, ‘test')]

7) Selenium內部運行機制是這樣的?爲何Selenium腳本能夠運行在幾乎全部的主流瀏覽器上。

答:Selenium的核心是Javascript寫的,它經過javascript來 實現對Html頁面的操做的。它提供了豐富的指定Html頁 面元素和操做頁面元素的方法。Selenium打開瀏覽器時,把本身的JavaScript文 件嵌入網頁中。而後Selenium的網頁經過frame嵌入目標網頁。這樣,就能夠使用Selenium的JavaScript對象來控制目標網頁。由於selenium是用javascript去操做頁面元素,因此支持幾乎全部主流的瀏覽器。

8) Selenium用javascript去操做頁面元素會碰到什麼問題? Selenium是如何解決這個問題的?

答:javascript受同源策略的限制。當瀏覽器要運行一個腳本時,便會進行同源檢查,只有和被操控網頁同源的腳本才能被執行。

Selenium經過採用代理模式來解決這個問題。測試腳本向Selenium Server發送Http請求,要求和Selenium Server創建鏈接。Selenium Server啓動瀏覽器,把Selenium Core加載入瀏覽器頁面當中,並把瀏覽器的代理設置爲Selenium Server的Http Proxy。測試腳本向Selenium Server發送Http請求,Selenium Server對請求進行解析,而後經過Http Proxy發送JS命令通知Selenium Core執行操做瀏覽器的動做。Selenium Core接收到指令後,執行操做。Selenium Server接收到瀏覽器的發送的Http請求後,本身重組Http請求,獲取對應的Web頁面。Selenium Server的Http Proxy把接收的Web頁面返回給瀏覽器。由於瀏覽器存在同源策略,因此Selenium RC中的Selenium Server須要以這種代理模式運行

  1. Ruby-Watir

1) 對於Javascript生成的元素,Watir識別和操做該元素是如何作的?

答:實際上,Watir::IE封裝了一個當前頁面的DOM tree,而不是html source。好比若是用javascrīpt動態產生一個元素,在這裏仍然能夠訪問。普通元素,按照Watir封裝的類就能夠實現訪問和操做。Windows對象支持並很差。

詳細參考該篇文檔:http://www.51testing.com/?uid-84226-action-viewspace-itemid-147237

2) 對於多瀏覽器的web測試,Ruby-watir是如何支持的?

答:Watir,FireWatir,SafariWatir各自的類庫支持,然而對於多瀏覽器的web自動化case編寫,不建議直接使用各個類庫去編寫case。在支持各瀏覽器操做的類庫之上進行一層封裝。在自動化case中不須要去關注各個瀏覽器的操做之間的區別,只須要經過封裝的類庫直接初始化相應的瀏覽器實例便可。

3) 簡述ruby-watir中如何實現數據驅動。

答:將與邏輯無關的數據剝離開來,多組數據做爲一組輸入,循環調用重複的用例接口。在ruby-watir中,支持讀取Excel等多種數據管理格式。

4) Ruby-watir中對於正則的支持,正則表達式的考察。

答:在Ruby中,要創建一個正則表達式,只要把要匹配的模式放到兩個斜線中就好了(/pattern/),並且,在Ruby中,正則表達式也是對象,能夠像對象同樣被操做。

例如,匹配Email地址的正則表達式:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*等。

5) watir不支持的windows控件,是如何解決的?

解答:採用第三方autoit技術,來模擬鍵盤或鼠標操做。參考

http://wiki.openqa.org/display/WTR/JavaScript+Pop+Ups

6) 簡述ruby元編程的概念,應用場景,以及如何應用。

答:一般元編程被認爲是經過程序來生成程序,在Ruby中,Ruby元編程的使用變得至關的簡單和容易實現,使用Ruby語言自己來產生Ruby代碼,不須要藉助外部的工具,著名的RoR框架就是創建在Ruby元編程的基礎上的。

好比ROR框架中的

class Person  

attr_reader :name  

end

attr_reader的實現以下:

# def attr_reader(*syms)  

# syms.each do |sym|  

# class_eval %{def #{sym}   

# @#{sym}  

# end  

# end   

# end

#注:class_eval是爲一個class增長method的。能夠接string和block爲參數。

在ROR框架中已經普遍應用了元編程,ActiveRecord在OR映射模型中,將關係數據庫中的關係表映射到對象模型時,將關係表的表名映射到類名,表中的每個元組映射到對應於這個類的一個對象,元組的一個字段對應於對象的一個屬性。ActiveRecord在這裏靈活應用了ruby元編程的動態特性,實現了優雅的解決方案。51Testing軟件測試網&S9ttat hFh}

  1. QTP:

1) 簡單介紹下QTP

答:QTP是個用於錄製和回放腳本的自動化測試工具。它能夠用於web和客戶端程序的自動化測試。

2) QTP中RO與TO的區別?

答:TO是Test Object的簡稱,RO是Runtime Object簡稱,既用來區分倉庫對象和實際對象,又用來區分對象的封裝接口和自身接口。

從實際做用上來看,應該說TO就是是倉庫文件裏定義的倉庫對象,RO是被測試軟件的實際對象。

爲用戶提供了兩種操做對象的接口,一種就是對象的封裝接口,另外一種是對象的自身接口。對象的自身接口是對象控件自己的接口,對象的封裝接口是QTP爲對象封裝的另外一層接口,它是QTP經過調用對象的自身接口來實現的。兩種接口的腳本書寫格式的差異在於:自身接口須要在對象名後面加object再加屬 性名或方法名,封裝接口就不用在對象名後面加object.

3) QTP中OBJECT SPY的做用?

答:查看對象,在查看窗口裏有列出這些接口,包括屬性和方法。

窗口中間有選擇欄讓你選擇Run-time Object或者Test Object,當你選擇Runtime Object時,它顯示的就是對象的自身接口(自身的 屬性和方法).當你選擇Test Object時,它顯示的就是對象的封裝接口(封裝的屬性和方法)

4) 如何激活一個窗口?

答:激活窗口使用的方法Window("").Activate

5) 編寫一個QTP腳本,實現向記事本中輸入「baidu」。 

答:SystemUtil.Run 「C:\WINDOWS\system32\notepad.exe」

Window(」Notepad」).Activate

Window(」Notepad」).WinEditor(」Edit」).Type 「baidu」

  1. LoadRunner

1) 什麼是負載測試?什麼是性能測試?

答:負載測試是經過改變系統負載方式、增長負載等來發現系統中所存在的性能問題。負載測試是一種測試方法,能夠爲性能測試、壓力測試所採用。負載測試的加載方 式也有不少種,能夠根據測試須要來選擇。

性能測試是爲獲取或驗證系統性能指標而進行測試。多數狀況下,性能測試會在不一樣負載狀況下進行。

壓力測試一般是在高負載狀況下來對系統的穩定性進行測試,更有效地發現系統穩定性的隱患和系統在負載峯值的條件下功能隱患等。

2) 性能測試包含了哪些測試(至少舉出3種)

答:壓力測試、負載測試、併發測試、可靠測試、失效恢復測試。

3) 簡述使用Loadrunner的步驟

答:腳本錄製設置—錄製腳本—調試腳本—場景設置—結果分析

4) LoadRunner由哪些部件組成?你使用LoadRunner的哪一個部件來錄製腳本, 哪一個部件能夠模擬多用戶併發下回放腳本?

答:virtual user generator

controller

analysis

virtual user generator 來錄製腳本,controller來回放腳本

5) 什麼是集合點?設置集合點有什麼意義?Loadrunner中設置集合點的函數是哪一個?

答:集合點:設置多個用戶到達某個用戶數量點集合,同時觸發一個事務,以達到模擬真實環境下同時多個用戶操做,同時模擬負載,實現性能測試的最終目的

LR_rendezvous(「集合點名稱」)

6) 你在LR中如何編寫自定義函數?請給出一些你在之前進行的項目中編寫的函數。

答:在建立用戶自定義函數前咱們須要和建立DLL(external libary)。把庫放在VuGen bin 目錄下。一旦加了庫,把自定義函數分配作一個參數。該函數應該具備一下格式:__declspec (dllexport) char* <function name>(char*, char*)。

7) 以線程方式運行的虛擬用戶有哪些優勢?

答:VuGen提供了用多線程的便利。這使得在每一個生成器上能夠跑更多的虛擬用戶。若是是以進程的方式跑虛擬用戶,爲每一個用戶加載相同的驅動程序到內存中,因 此佔用了大量的內存。這就限制了在單個生成器上能跑的虛擬用戶數。若是按進程運行,給定的全部虛擬用戶數(好比100)只是加載一個驅動程序實例到內存 裏。每一個進程共用父驅動程序的內存,所以在每一個生成器上能夠跑更多的虛擬用戶。

相關文章
相關標籤/搜索