文章目錄
- 前言
- 面試背景及準備
- 電話面試所問的問題
- 1.自我介紹&語法基礎
- 2.面向物件程式設計
- 3.計算機網路及記憶體管理
- 4.作業系統
- 5.資料結構和演算法設計
- 6.專案考察
- 7.尾聲
- 更新
前言
由于面試時候的問題和回答全都是后來憑著記憶寫出的,因此難免會有遺漏,但大致的問題流程與實際面試時基本無二,這里記錄下來,算是一個經驗的分享與積累吧,
面試背景及準備

我投遞的是C/C++的后臺開發崗,大概是在20號左右投遞的簡歷,三天后就收到了面試官的電話,當時收到電話但聽不到對方的聲音,還以為是打錯了,掛掉后過了半分鐘又收到了面試官的電話,告知我看了我的簡歷,問我有沒有興趣參加面試(這途中我的聽筒聲音斷斷續續,不知道是哪邊的問題),因為下午有一些急事,所以定了晚上七點的電話面,
面試官在電話里說會問一些關于C/C++的知識,因為不確定會不會考演算法和資料結構,所以我就多嘴問了一下,得到的答復是可能會有涉及(后來想了一下,大概就是,如果前面語法部分答得還說得過去,就會往后深入問,不然甚至到不了問演算法的環節就結束面試),我緊接著問了會不會考TCP/IP相關,話剛問完,那邊就掛了電話(同樣不知道是哪邊問題,當時心里慌得一批,以為是自己多嘴,面試官生氣了),
下午空閑下來,就塌下心開始準備,因為準備考研,很久沒用C++做專案了,于是從12點一直準備到了下午七點,主要復習的就是C++的一些基本語法、細節以及特性,最后看了看自己簡歷上寫的專案,復盤了一下代碼,
這其間并沒有準備什么資料結構和演算法方面的知識,
電話面試所問的問題
1.自我介紹&語法基礎
Q: 今天上午我們聯系過了,現在你那邊有時間吧(嗯嗯有的),那就先自我介紹一下吧,
A: 您好,我叫xxx,是一名來自北京建筑大學的大四學生,現在是一名共產黨員,從大一開始我就愛上了編程,很享受專案在自己手里完成的那種成就感,大一剛開學四五個月,就自己動手實作了一些諸如2048、貪吃蛇之類的小游戲,后續也開發了一些小的專案,比如我簡歷里寫的疫情期間全自動打卡系統,軟體管理平臺,Linux基于socket的多人聊天室等,因為現在已經大四,也要步入社會了,作為一名計算機系大學生,很渴望能到小米這樣的好企業來發展,
Q: 好的,那就開始面試吧,我們先從簡單的C/C++語法問起,后續再看看問點專案里的東西,你先來說一下C語言里struct和union的區別吧,
A: struct直白來講就是實作了類似于C++里class的作用,里面可以定義一些成員屬性和方法,以實作封裝的操作,
Union我隱約記得是類似于一個字典,實作了從變數到某一值的映射,(后來發現自己這里記錯了,當時還說的一本正經,真就是一本正經的胡說八道)
Q: 那你來說一下union和struct在計算占用記憶體上的方法吧,
A:union沒了解關于計算記憶體的方法,所以不是太清楚,struct是根據對齊原則計算,比如結構體里有多個型別的變數,像int,char等,計算時的最終結果應該是struct中變數占用空間最大的記憶體的倍數,
Q:struct計算時有沒有什么容易踩的坑呢?
A:…(沉默)
Q:比如計算含有多種不同資料型別的struct的時候,應該滿足對齊原則,這地方你知道嗎?
A:這部分我前面提到了…
Q:嗯嗯,那你有用過位元組對齊嗎?
A:(實話實說)沒有,
Q:但我看你的簡歷里寫你在Linux下做了一個socket編程的專案,socket編程就是需要用到位元組對齊的,這部分怎么做的呢?
A:(實話實說)因為當時這個socket聊天室是Linux課設的一個選題,當時的時間非常短,只有兩三天,為了趕進度,又想完成這個專案,我借鑒了書上部分固定的代碼片段,因此這部分就沒有深究,
Q:好的,那現在問一下C語言里的static,const吧,你先來說一下對static的理解,
A:static宣告的資料是存放在C語言記憶體布局下的靜態變數區的,它的作用域是區域、而生命周期是整個程式運行,static宣告的靜態區域變數,只有在第一次進入函式時會被初始化,例如我有一個函式function(),在函式中static int 了一個整型靜態區域變數,function里每次將這個整型變數自增1,那么第二次呼叫function的時候,這個整型值就變成了2,第三次是3,以此類推,
static具有區域可見的性質,例如對于用static宣告的靜態全域變數,它的作用于就限制在了本檔案,其他外部的程式想要用extern訪問static宣告的變數時,會報變數存在于另一檔案的錯誤,
C++中的類里使用static只會被分配一次記憶體,不管使用這個類創建了多少個物件,
Q:OK,那談一下const和define的區別吧,
A:(思考…)
我先來說一下C中程式執行的程序吧:預處理、編譯、匯編、鏈接,define是用來做宏定義的,用define宣告的宏就是在預處理階段被替換,這個階段編譯器同時會做一下諸如洗掉注釋之類的操作,而const宣告的變數則是在編譯階段被編譯的,大概就是這樣,
Q:你說的沒錯,但不是最主要的,區別主要有兩個,你說的算一個,另一個我提醒一下吧,define和const,是否都要型別檢查呢?
A:(恍然大悟)#define只是簡單的字串替換,沒有型別檢查,而const是要進行判斷的,
Q:那你知道const在編譯階段會被編譯成什么匯編代碼嗎?
A:不知道,沒涉及過,
Q:好的,接著說一下C語言和C++的區別吧,
A:我覺得這其中最大區別就是:C語言是面向程序的,比如完成一件事需要幾步,需要幾種方法,把這些方法對應寫成函式,
C++是面向物件的,例如有一個物體,它具有一些屬性和操作,我們就可以把這個物體的所有屬性和方法進行封裝,變成一個整體,對這個類的操作就更好的體現了結構性,
2.面向物件程式設計
Q:既然說到了面向物件,來說說面向物件的幾大特點吧,
A:面向物件的特點有:封裝性,繼承以及多型,封裝性就是前面提到的,將一個物體的屬性和方法封裝成一個整體,繼承就是指,例如我們有好幾種圖形,分別是三角形,四邊形,五邊形等,而這些不同形狀的本質都是多邊形,我們就可以創建一個多邊形的基類,讓這些多邊形都作為基類的派生類,繼承基類的屬性,
關于多型,其實就是用創建的基類指標去指向派生類的物件,對基類指標方法的訪問就可以達到呼叫派生類對應的函式的目的,
Q:嗯嗯,多型的實作方法有什么呢?
A:我只知道可以通過virtual實作多型,其他記不太清楚了,
Q:既然提到了virtual,你來說一下virtual是什么吧,
A:virtual用于宣告虛函式,虛基類,如果沒有將基類中的函式宣告為virtual的話,就算用基類的指標去指向派生類,呼叫派生類的方法,最后運行的結果也全都只會是基類的,這是因為靜態鏈接(靜態系結)的原因,也就是說函式呼叫在程式執行前就準備好了,
使用了virtual之后,會告訴編譯器不要靜態鏈接到定義的虛函式,也就實作了動態系結,
Q:好的,你說的是動態實作多型,還有一個靜態的方法,能說一說嗎,(這里我記不起來了,面試官接著說:)實作多型還有一種方法,就是多載,這個你來簡單說一下吧,
A:多載就是可以宣告幾個具有不同引數串列(例如引數的型別,個數,順序不同)的同名函式,這些函式可以實作不同的功能,
Q:可以把一個函式多載成多個,多載多個函式的區別是什么呢?
A:引數型別、個數、順序都可以不同,
Q:如果只是回傳值不同可以嗎?
A:不行
3.計算機網路及記憶體管理
Q:tcp三次握手了解嗎,來簡單說一下握手的程序,
A:tcp的三次握手程序是這樣的:有一個發送端,一個接收端,發送端想要發送資料給接收端,就需要發送一個sychronize的報文,代表“我給你發送訊息了”,接收端接受到后,會發送sychronize/acknowledge的報文,代表“我接受到了你的報文”,發送端接收后,會接著回傳一個報文,代表“我知道你知道我發送了”,
Q:嗯,那你說一下指標和參考的區別吧,
A:先說一下最本質的區別,指標的本質就是一個特殊的變數,它存放的是地址,指向一個存盤單元;而參考其實就是原變數的一個別名,和原本的變數實際上就是同一個東西,
Q:C語言里對記憶體進行處理的函式都用過哪些,
A:分配用的malloc,釋放使用的free,malloc是在堆上分配連續記憶體給用戶,若想擴大malloc初始分配的記憶體,需要重新給用戶分配一個滿足要求大小的連續記憶體區,
Q:malloc以及包括new都會導致一些安全問題,C++11里引入了什么資料結構或者資料型別,可以解決這種安全問題,你知道嗎?
A:不太清楚
Q:智能指標可以解決這個問題,你有了解嗎,
A:(恍然大悟)聽說過,但沒用過,
Q:malloc底層實作了解嗎,Linux內核上分配空間的函式有什么呢?
A:沒接觸過,不是很了解,
4.作業系統
Q:內核上有kmalloc和vmalloc,你既然沒接觸過,那后面應該也就不清楚了,看你簡歷上CSDN博客里有一些演算法和資料結構的知識,你也是學計算機的吧,我也是計算機科學與技術的,那我們就聊一下作業系統相關的知識吧,先來簡單說一下行程和執行緒吧,
A:行程是資源分配和調度的基本單位,執行緒是程式運行的基本單位,一個行程可以創建多個執行緒,這些執行緒共享該行程的記憶體空間,且每個執行緒之間有獨立的堆疊,引入執行緒之后,程式的并發性就進一步提高了,可以說執行緒比行程有更好的并發性,
Q:好的,那來說一下行程通信的方法都有哪些,
A:管道pipe,訊息佇列,共享記憶體,共享記憶體就是…
Q:(打斷)不用展開說這部分,你說的是其中三種,應該還有其他方式,是什么呢?
A:記不太清了,
Q:管道分為兩種,有名管道和無名管道,這兩種的特點和實作方式說一下吧,
A:也記不得了,不好意思,
Q:我來提醒一下吧,有一種通信方式是信號量機制,可以實作同步和互斥(我心里:最近考研復習的就是這個,一拍腦袋恍然大悟),行程的同步互斥可以通過信號量機制實作,那么執行緒是否也有相應的實作方式呢?
A:(想了半天)我記得有個管程,是可以實作對同步互斥進行封裝,使得程式員可以更便捷的操作執行緒,
Q:管程…我沒聽說過,是不是你編的我也不知道(我…),纖程是可以實作管理執行緒的,這個了解嗎?
A:聽說過,但沒用過,
Q:平時大多在什么作業系統上做專案呢?
A:一般是在windows,因為之前做的專案主要使用C/C++,java,Python,在Windows上的表現效果也是比較好的,但學Linux編程的時候是在Linux下撰寫的socket聊天室,所以也涉及到了Linux,
Q:Linux下會用到一些命令列,也叫做shell的命令,那你來說一下shell里是如何改變檔案權限的吧,
A:可以通過chmod改變權限,比如chmod 777之類的,
Q: 像你所說的,可以使用chmod改變檔案權限,那chmod后面的不同數字對應不同權限,來講一下這些數字都有什么,分別對應什么權限吧,
A: 不好意思,我只記得chmod 777了,是可讀可寫可執行,其他的數字權限也用過,但都是邊查邊學邊用,所以記得不是很清楚,
5.資料結構和演算法設計
Q:好的,我看你簡歷上面寫的博客,里面涉及一些演算法題,我就拿這考考你吧,回文串判定的演算法,簡單說一下吧,
A:可以設定雙指標分別指向串的首尾,類似于火車碰頭問題,兩側向中間依次遍歷并檢查所比較的當前元素是否相等,若回圈直至碰頭,代表是回文串,中間停止則不是,
還有一種方法,可以設定一個堆疊,將回文串入堆疊,利用堆疊后進先出的特性與原串彈出比較,
Q:接著說一下水仙花數的判定吧,
A:不好意思,太久不做OJ,記不得什么是水仙花數了,
Q:(水仙花數類似于回文串判定,只不過是一個整體)你那會說的演算法并不是判斷回文串的最好演算法,會有冗余的串,還能想到其他的嗎,
A:效率高的那個演算法不太記得了,我能想到的暫時只有一種暴力的方法,也就是依次除十取余,商零為止,再將取到的位數放入陣列或者串存盤,最后利用上面提到的回文串判斷演算法進行判斷,
Q:說一下單鏈表和雙向鏈表的各自特點和對比,
A:單鏈表只有一個next指標用于指向下一個節點,雙聯表附設了一個prior指標指向前驅節點,這樣單鏈表在洗掉一個元素時,就需要設定前驅指標pre來判斷pre->next是否等于要洗掉的節點,若是,則將pre->next指向下一個節點,而雙向鏈表由于有pre指標,就無需如此,
單項鏈表由于單向的性質,只能從鏈表的頭結點開始依次向后遍歷訪問,雙向鏈表則可以附設一個指標指向鏈表尾部,從而達到從后向前遍歷的目的,
舉個例子,同樣是訪問倒數第二個元素,用單鏈表實作時,一種比較好的方法是,需要使用雙指標,讓一個指標從鏈表頭開始遍歷,一個從鏈表的第二個節點開始遍歷,這樣當前面的指標走到末尾時,后面的指標就指向了倒數第二個節點,
但對于雙向鏈表來說,一旦保存了尾指標,只需要通過prior進行訪問倒數第二個元素,
Q:那如果我想要判斷單鏈表是否有環,請你設計一個演算法吧,
A:(思考了10秒),可以使用快慢指標的方法,設定快慢指標均指向頭結點,一個慢指標一次走一步,另一個快指標一次性走兩步,如果快指標始終未指向NULL,且快慢指標最終相遇,就代表單鏈表是有環的,如果快指標走到了NULL但未和滿指標相遇,證明無環,
Q:堆疊和佇列有什么區別呢?
A:堆疊是后進先出,佇列是先進先出,
舉個例子:比如老師收作業,會把最后交的放在最上面;判作業的時候,會從最上面拿起最后交的學生的作業,最先批改,這就類似于堆疊,再比如學生排隊打飯,最先排隊的學生肯定會最先吃到飯,這就類似于佇列,
Q:佇列里有個特殊的叫做優先佇列,說一說你的理解,
A:優先佇列就是根據某種優先級規則,讓優先級高的元素先行出隊的佇列,這個優先級是可以自己設定的,比如單純的優先級,或者數值的大小等,
Q:C++里有個STL,全稱是什么 知道嗎?
A:到嘴邊就是想不起來了,(思考6秒)哦對,是標準模板,
Q:你用到過哪些呢?
A:vector,set,map都用過,
Q:vector都有哪幾種資料結構呢?
A:順序表:線性表,鏈表,其他不知道了,
Q:set里元素是遞增的?遞減的?還是無序的?
A:遞增的,且唯一,例如1這個元素,在set里只能出現一次,
Q:對,map里面有個特殊的,叫做hash_map,hash_map有幾種解決哈希沖突的方法,簡單說一下,
A:(說了線性探測再散列,還有平方探測,)
Q:map的底層實作用的什么資料結構呢?
A:(想了想)紅黑樹,
Q:紅黑樹的原理知道嗎?
A:沒用過,不知道,
Q:那你知道平衡二叉樹嗎,說一下,
A:平衡二叉樹的每個節點的左右子樹高度差的絕對值不超過1,這樣遞回定義每個節點就構成了平衡二叉樹,
6.專案考察
Q:好的,我們現在進入專案環節,你說的第一個專案用到了python+selenium,這里selenium是一個庫嗎?
A:是的,是用于實作自動化的一個庫,可以模擬用戶的真實操作,例如點擊button等,
Q:說一下原理吧,
A:我們登錄網頁就可以查看網站web的源代碼,selenium先是會加載一個瀏覽器的驅動,比如我這里使用的就是Firefox的驅動,加載了驅動后就可以模擬用戶手動打開瀏覽器,之后是定位元素,舉個例子,selenium通過一個button的id或者class定位到這個button,并通過呼叫find_element_by_id().click()的方式點擊提交,
Q:你這個應該只是基于靜態頁面吧,如何處理動態頁面的一些反爬和防注入的手段,導致沒辦法爬取的問題呢?這個有做過嗎?
A:有的,我的這個疫情期間自動打卡專案中有一個id的定位就是一直不成功,后來我同時打開兩個頁面的源代碼進行對比,發現相同button的id均具有相同前綴fs_tab_,但后綴不同,這些后綴可能是MD5碼,也可能是隨機生成的,通過分析發現,可以使用模糊匹配的方式定位到這個button,而不必全串匹配,實作了防止反爬的手段,
Q:你提到了模糊匹配,那應該用到了正則運算式吧,
A:并沒有,這里的selenium提供了現成的start_with方法,可以實作模糊匹配,
對了,我之前還做過一個專案,是爬取一個動漫網站的,那個網站通過反爬手段,使得我爬取的照片鏈接總是失效的,后來想到了一種解決方案,也就是通過Python庫函式進行截屏,因為漫畫出現的區域是固定的,這樣通過裁剪指定區域就可以實作圖片的獲取了,
7.尾聲
Q:好的,面試到現在也快一個小時了,也差不多該結束了,咱們隨便聊一聊吧,我現在在小米做的是相機工程師,你在這之前簽了其他公司嗎?
A:沒有,
Q:(有些驚訝)那拿到了多少個offer了?
A:沒拿到過,小米是面試的第一家,
Q:(十分驚訝)你們現在不應該是…
A:我是準備了考研的,但是覺得如果本科畢業就能來到小米這樣的好公司,就暫時不讀研了,我很喜歡小米的企業文化,相比某為這些公司就很人性化,很讓人舒服,當然,如果沒能成功拿到offer的話,我就去讀研,目標是北京郵電大學,
Q:確實,但其實來小米作業三年,和那些研究生上了三年學最后出來找到的作業是基本一樣的,而且你能在小米作業三年,可能比研究生讀完出來的發展還要好,
Q:最后,你有什么想問的嗎?
因為看到網上經驗貼說一定要問點什么,我就問了小米手機部的歷史,發展前景,
面試官也和我聊了聊自己的作業,我告訴面試官自己對小米有一種情結,第一部智能手機就是小米的“小米1S”,現在用的手機是小米的“紅米K30PRO”,感慨了一下現在手機相機防抖演算法和高焦距下畫質處理的快速發展,
最后面試官告訴我hr會在兩三天行內系我,讓我做好準備,
更新
一天后的今天,順利收到了HR的offer call,拿下了小米手機部某技術崗位的offer,要感謝的人實在太多了!不得不感慨小米招聘的速度之快,這是我面試的第一家公司、拿到的第一個offer,這份經歷彌足珍貴!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/227532.html
標籤:其他
上一篇:末流985碩士強行轉行java后端開發,兩個月秋招總結,已拿5個offer!
下一篇:STM32新手入門教程
