天天看點

騰訊微信事業部後端開發一面涼1 思考2 題目整理

1 思考

效率:有一說一,騰訊是真的效率。3月24号下午六點左右投了實習,晚上7點半發來郵件,約第二天下午兩點半開始面。畢竟第一次,緊張又激動,考慮再三還是接手了第二天的面試。此前投了華為、位元組,時間隔得較久,華為公共事業部打了電話問武漢的測試崗,隻說先準備筆試,還沒有約具體時間。其他機關投的較晚,還沒有接到電話。另外,騰訊實習似乎沒有筆試,直通面試。

面試内容:這方面準備做的不夠,不是說知識技術做的不夠,是指對每個公司了解不夠。騰訊這邊主要開發語言是c++和c,我主要準備的是java,是以面試的時候面試官想問我的和我所知道的差距很大。java上邊的東西問的很少,大概圍繞面向對象、hash表、二叉樹這些語言相關性不大的問題,考了一道算法:使用數組實作循環隊列。感覺挺簡單,但是最後沒實作出來,隻能說準備不足吧,這是要重點反思的地方。除了這些,重點問了作業系統裡邊的一些概念,比如:程序、線程、協程;程序間通信。深度不是很深,之前如果看過相關内容的話,應該能答個七七八八。

其他方面:面試官人很好,開始面之前緊張的不行,大學大三大四沒抓住機會,導緻研一才進行第一次面試,不是遠端面試的話,估計舌頭都縷不順…開始面了就沒那麼緊張,面試官給人的感覺溫文爾雅,有時候看你不說的不對,還會給點小提示,整個面試氛圍非常友好。奈何欠缺準備QAQ,隻能繼續加油吧。

25号下午面完之後,下午4點半左右,騰訊雲存儲打來電話約晚上7:30面試,因課推到了周一。意思是第一個部門已經挂了,又有幸被新部門撈到。再次強調,效率真的高。

對話補充,T代表騰訊,W代表我。

W(小心翼翼):你們那邊主要用C++嗎,我平時主要學的java,要不要提前準備一下?

T(豪爽大氣):是的,我們這邊全員c++。這個沒關系,那我到時候主要問一些算法等語言無關的東西,我們不太指望實習生能做太多工作,面試過了再學就可以了!

W(痛哭流涕,我一定好好學習QUQ,争取早日996QUQ…)

2 題目整理

面試過程沒有錄音,憑借會議大概整理一下,希望下次再遇到這樣的問題回答流利,不再出錯。

2.1 語言基礎

1. 面向對象三大特性

封裝:把客觀事物封裝程抽象的類,并且把自己的資料和方法隻讓可信的類或者對象操作,對不可信的進行資訊隐藏。簡單說,一個類就是一個封裝了資料以及操作這些資料的代碼的邏輯實體。通過這種方式,對象對内部資料提供了不同級别的保護。

四種權限修飾符及作用範圍

騰訊微信事業部後端開發一面涼1 思考2 題目整理

目的:增強資料安全性,不讓其他使用者随意通路和修改資料。簡化程式設計,使用者不需要在意具體實作細節,而隻需要通過外部接口即可通路類的成員。

繼承:繼承是指從已有的類中派生出新的類,新的類能吸收已有類的資料屬性和行為,并能擴充新的能力。繼承的類叫做子類,被繼承的類叫做父類。

java中的繼承

java通過extends關鍵字來實作繼承。java中一個類隻能繼承一個父類,且隻能繼承通路權限非private的屬性和方法。

目的:實作代碼複用。

多态:多态分為兩種:編譯時多态、運作時多态。

編譯時多态:即重載(Overload)。是指在同一個類中,方法名相同,參數清單不同的多個方法構成多态。參數清單不同主要包括:參數順序、參數數量、參數類型。而無關方法傳回值、權限修飾符。

運作時多态:即重寫(Override)。發生在子父類之間,子類重寫父類方法。要求兩同兩小一大:方法名和參數清單必須相同、子類傳回值類型和抛出異常小于父類傳回值類型和抛出異常(子類傳回類型或異常可以使父類傳回類型或異常的子類)、子類權限修飾符大于父類權限修飾符。

目的:增加代碼靈活性。

2. 面向對象和面向過程

面向過程:分析出解決問題所需要的的步驟,然後用函數将這些步驟一步一步實作,使用的時候依次調用即可。

優缺點:

優點:性能高于面向對象,減少類執行個體化所需的開銷。

缺點:難維護、難複用、難擴充。

面向對象:把構成問題事物分解成各個對象,建立對象的目的不是為了完成一個步驟,而是為了描述某個事物在整個解決問題的步驟中的行為。面向對象即在程式設計的時候去模拟真實的世界,按照現實世界中的邏輯去處理一個問題。

優缺點:

優點:易維護、易複用、易擴充。封裝、繼承、多态,容易設計出來低耦合的系統。

缺點:性能較低。

2.2 資料結構

2.2.1 哈希表

概念:哈希表又稱散清單,它遵循函數映射思想,以Key:Value的方式存儲資料。哈希表最大的特點是可以快速定位到要查找的資料,查詢的時間複雜度接近O(1)。是一種空間換時間的存儲結構。

哈希函數:用于映射的函數稱為哈希函數,哈希函數需要考慮多個因素:關鍵字的長度、哈希表的大小、關鍵字的分布情況、記錄的查找頻率等等。主要有以下幾種哈希函數:

直接尋址法:取關鍵字或者關鍵字的某個線性函數值為散列位址。

數字尋址法:通過對資料的分析,發現資料中心沖突較少的部分,構造散列位址。比如學号,前幾位一般相同,取後幾位作為散列位址。

平方取中法:可以先求出關鍵字的平方值,然後按需要取平方值的中間幾位作為散列位址。

取随機數法:使用随機函數,取關鍵字的随機值作為散列位址。

除留取餘法:取關鍵字被某個不大于散清單長n的數m除後所得到的餘數p為散列位址。

沖突:函數映射中有一個典型的特點是兩個自變量可以同時對應一個因變量。哈希表中也存在同樣的情況,但是由于哈希表計算出來的值是一個位址,同一個位址隻能存放一個資料。是以如果兩個數最後求得的值是相等的,那麼這個位址是放數a呢還是放數b呢,這時候就會産生沖突。解決沖突的方法有以下幾種:

拉鍊法:将有沖突的資料放在一個連結清單中,查詢時根據key查到連結清單的第一個節點,然後周遊整個連結清單,找到相應的值。

開放定址法:通過對計算出來的位址進行一個探測,比如往後移動一個位址,如果沒人占用,就用這個位址。

再哈希法:産生沖突之後,使用關鍵字的其他部分繼續計算位址。

哈希表的特點

哈希表有兩種用法:一種是Key的值和Value的值相同,這種結構為Set;如果Key和Value對應的内容不同,稱這種結構為Map。

  1. 通路速度快。在O(1) 複雜度查詢到結果。
  2. 空間使用率不高。哈希表實際上是存不滿的,當哈希表存的資料越多,發生沖突的機率越大,處理沖突所需的時間越高,效率越低。空間換取時間。
  3. 無序。為了更快地通路元素,哈希表是根據散列函數直接找到存儲位址的,通路更快,但是無法實作有序的通路。
  4. 可能會發生碰撞。沒有完美的散列函數,無論如何總會發生沖突,是以需要沖突解決方案。

哈希表使用場景

檢驗安裝檔案的完整性:在軟體部署時,計算軟體包目前的哈希值與預設值相等,防止軟體包被篡改或替換。

存儲和校驗使用者密碼:使用者密碼不能用明文存儲。雜湊演算法可以做到既不知道使用者明文,又可以校驗使用者密碼。

資料庫表分區的條件:如果按照某一個列隊資料庫表做分區,表中的資料又沒有太多的業務邏輯,那麼通過哈希函數強行分區是個不錯的選擇。

2.2.2 循環隊列

使用java中的泛型手撕循環隊列。

問懂不懂泛型,用泛型實作一個循環隊列。答用過,知道怎麼用,但是自己寫的類中沒有用到過泛型。問沒關系,不使用泛型實作一個。

屬實菜雞,要求已經夠低了,沒寫出來我反思。

public class Main {
    public static void main(String[] args) {
        MyQueue queue = new MyQueue(String.class,5);
        queue.push("11");
        queue.push("22");
        queue.push("33");
        queue.push("44");
        queue.push("55");
    }
}

class MyQueue<T>{
    private T[] array;
    private int front;
    private int rear;
    // 實際開辟的數組大小,比隊列大小大1
    private final int capatity;

    // 建立隊列
    public MyQueue(Class<T> clazz,int size) {
        this.capatity = size + 1;
        array = (T [])Array.newInstance(clazz, capatity);
        front = 0;
        rear = 0;
    }

    // 進隊
    public void push(T element){
        if(((rear + 1) % capatity) == front){
            front = (front + 1) % capatity;
        }
        array[rear] = element;
        rear = (rear + 1) % capatity;
    }

    // 出隊
    public T pop(){
        T element = array[front];
        front = (front + 1) % capatity;
        return element;
    }

    // 判空
    public boolean isEmpty(){
        return front == rear;
    }

    // 求容量
    public int size(){
        return (rear - front + capatity) % capatity;
    }

    // 傳回隊頭元素
    public T top(){
        if(isEmpty()){
            throw new RuntimeException("隊列為空");
        }
        return array[front];
    }
}
           

2.3 作業系統

2.3.1 程序、線程和協程

程序:程序是一個具有一定獨立功能的程式在一個資料集上的一次動态執行的過程,是作業系統進行資源配置設定的基本機關,是應用程式運作的載體。程序一般由程式、資料、程序控制塊三部分組成。

程式用于描述程序要完成的内容,是控制程序執行的指令集。

資料是程式在執行時所需要的的資料和工作區。

程序控制塊,包含程序的描述資訊和控制資訊,是程序存在的唯一标志。

線程:線程是程式執行中一個單一的順序控制流程,是程式執行流的最小機關,是處理器排程和分派的基本機關。一個程序可以有一個或多個線程,各個線程之間共享程序的記憶體空間。一個标準的線程由線程ID、程式計數器、寄存器和堆棧組成。

協程:協程是一種基于線程之上,又比線程更加輕量級的存在,這種由程式員自己協程式來管理的輕量級線程叫做使用者空間線程,具有對核心來說不可見的特性。正如一個程序可以擁有多個線程一樣,一個線程也可以擁有多個協程。

騰訊微信事業部後端開發一面涼1 思考2 題目整理

在傳統的J2EE系統中都是基于每個請求占用一個線程去完成完整的業務邏輯。是以系統的吞吐能力取決于每個線程的操作耗時。如果遇到很耗時的IO行為,則整個系統的吞吐量立即下降,因為這時候線程一直處于阻塞狀态,如果線程很多的時候,會存在很多線程處于空閑狀态,造成資源應用的不徹底。

對于這個問題,比較流行的解決方案是單線程加異步回調。

協程目的是當出現長時間的IO操作時,通過讓出目前的協程排程,執行下一個任務的方式,來消除下下文切換的開銷。

協程的特點

線程的切換由作業系統負責排程,協程由使用者自己進行排程,是以減少了上下文切換,提高了效率。線程預設的Stack大小是1M,協程更加輕量,接近1K。且在一個線程内,避免了競争關系而使用鎖。适用于被阻塞的,且需要大量并發的場景。不适用于大量計算的多線程。

原理

當出現IO阻塞的時候,由協程的排程器進行排程,通過将資料流主動讓出,記錄目前棧上的資料,阻塞完後立即再通過線程恢複棧,并把阻塞的結果放在這個線程上去跑,這樣看上去跟寫同步代碼沒什麼差別。

協程的暫停完全由程式控制,發生在使用者态;線程的阻塞狀态是由作業系統核心來進行切換,發生在核心态。

參考文章:一文讀懂什麼是程序、線程、協程

2.3.2 程序間通信方式

管道、消息隊列、共享存儲、信号量、Socket

1. 管道:一般指無名管道,是UNIX系統程序間通信最古老的方式。

特點:半雙工,固定的讀端和寫端;隻能在有親緣關系的程序直接進行通信;

FIFO命名管道:也是半雙工,但是可以在無關的程序之間進行資料交換;FIFO有路徑名與之關聯,以一種特殊的裝置檔案的形式存在于檔案系統中。

2. 消息隊列:消息隊列是消息的連結清單,存放在核心中。一個消息隊列有一個隊列辨別符來辨別。消息隊列克服了信号傳遞資訊少、管道隻能承載無格式位元組流以及緩沖區大小受限制等缺點。

特點:消息隊列是面向記錄的,其中的消息具有特定的格式和特定的優先級;消息隊列獨立于發送和接收程序,程序終止時,消息隊列及其内容不會被删除;消息隊列可以實作消息的随機查詢,消息不一定要以先進先出的次序讀取,也可以按消息的類型讀取。

3. 信号量:信号量是一個計數器,信号量常作為一種鎖機制,用于實作程序間的互斥與同步,而不是用于存儲程序間通信資料。

特點:信号量用于程序間同步,若要在程序間傳遞資料需要結合共享記憶體;信号量 基于作業系統的PV操作,程式對信号量的操作都是原子操作;每次對信号量的PV操作不僅限于對信号量值加1或減1,可以加減任意整數;支援信号量組。

4. 共享記憶體:共享記憶體指兩個或多個程序共享一個給定的存儲區。

特點:共享記憶體是最快的一種程序通信方式,因為程序是直接對記憶體進行存取;多個程序需要同時操作,是以需要進行同步;信号量+共享記憶體通常結合在一起使用,信号量用來同步對

5. Socket:套接字也是一種程序間通信機制,與其他通信機制不同的是,它用于不同機器間的程序通信。

特點:傳輸資料為位元組級,傳輸資料可自定義;傳輸時間短,性能高;适用于用戶端和服務端之間資訊實時互動;可以加密,資料安全性強。

2.4 其他

2.4.1 c++

這方面知識不打算準備,把問題記錄一下,感興趣的同學可以查一下看看。

c++中static關鍵字的含義以及用法。