2019年_BATJ大廠面試題總結-華爲篇

1.java的反射機制瞭解嗎

答案:https://blog.csdn.net/qq_39209361/article/details/81239189

2.Java的數據類型,線程,內存

答案:https://blog.csdn.net/zj15527620802/article/details/80622314
https://www.cnblogs.com/skorzeny/p/6480012.html

3.rabbitMQ有哪些關鍵的組成部分?

publisher
publisher:發佈消息
exchange
exchange:用來決定消息應該投遞到哪些queue
queue
queue:用來存儲並分發消息
consumer
consumer:消費消息
除此之外還有另外幾個概念

routing_key
搭配binding_key用來過濾消息,這個屬性會在消息發送時被決定
binding_key
用來綁定exchange和queue,和routing_key搭配在exchange決策哪些消息應該投遞到哪些queue
exchange的類型:FANOUT,TOPIC,DIRECT
FANOUT:廣播,此時binding_key和routing_key其實是無效的,消息將會投遞到目標exchange綁定的所有queue上
DIRECT:消息將只會被投遞到和routing_key一致的binding_key所綁定的queue上
TOPIC:和DIRECT相似,只是此時exchange的決策會考慮binding_key的通配符配置
詳解:https://www.cnblogs.com/200911/p/4856835.html

4.STL中vector和map的區別,map底層如何刪除一個元素

答案:
1、Vector是順序容器,是一個動態數組,支持隨機存取、插入、刪除、查找等操作,在內存中是一塊連續的空間。在原有空間不夠情況下自動分配空間。vector隨機存取效率高,但是在vector插入元素,需要移動的數目多,效率低下。
2、Map是關聯容器,以鍵值對的形式進行存儲,方便進行查找。關鍵詞起到索引的作用,值則表示與索引相關聯的數據。以紅黑樹的結構實現,插入刪除等操作都在O(logn)時間內完成
總結:
1、如果你需要高效的隨即存取,而不在乎插入和刪除的效率,使用vector
2、如果你需要大量的插入和刪除,而不關心隨即存取,則應使用list
3、如果你需要隨即存取,而且關心兩端數據的插入和刪除,則應使用deque。
刪除:https://blog.csdn.net/wxm349810930/article/details/69663287

5.String,StringBuffer,聊了比較多的String相關的

源代碼答案:https://www.cnblogs.com/kissazi2/p/3648671.html
詳解:https://blog.csdn.net/shenhonglei1234/article/details/54908934

6.對Spring的理解,說說裏面用到的設計模式

最詳細的答案:https://blog.csdn.net/xunjiushi9717/article/details/94322213

7.多線程中生產者和消費者如何保證同步

答案:https://blog.csdn.net/aaron072/article/details/78611849

8.瀏覽器輸入一個地址,數據在網絡中是怎麼傳輸的,每一層加了什麼

答案:https://blog.csdn.net/swag_wg/article/details/102214865

9.你用的java哪個版本,java1.8有什麼新特性

答案:https://blog.csdn.net/qq_29411737/article/details/80835658

10.你用過什麼消息中間件?(RabbitMQ)

答案:RabbitMQ 入門到精通(這一篇就夠了)

11.手撕代碼:

[A,A,A,B,B,C]每次只能存一個元素,耗時爲1時,相同元素需要隔n時才能存,問存的最小耗時。
思路:數據結構算法。

12.寫代碼:判斷一棵樹是不是平衡二叉樹

解決思路一:按照前序遍歷的路線判斷。

1.判斷以根結點的樹是否爲二叉平衡樹。求出左右子樹的高度,判斷它們的高度差是否超過了1。
2.遞歸判斷根的左子樹是否爲平衡二叉樹
3.遞歸判斷根的右子樹是否爲平衡二叉樹
注意:空樹也是平衡二叉樹
代碼實現:

//二叉樹的高度(比較左右子樹那個高,高的加1既爲二叉樹的高度)
int BinaryTreeHigh(BTNode* root)
{
    if (root == NULL)
    {
        return 0;
    }
    int ret1 = BinaryTreeHigh(root->_left);
    int ret2 = BinaryTreeHigh(root->_right);
    //二叉樹的高度爲左子樹和右子樹中高的那個高度加1
    return ret1 > ret2 ? ret1 + 1 : ret2 + 1;
}
//判斷樹是否爲平衡二叉樹(1:是 0:不是)
int IsBlancedTree_R(BTNode* root)
{
    //空樹是平衡二叉樹
    //平衡二叉樹是指以當前結點爲根的左右子樹高度不得超過1
    if (root == NULL)
        return 1;
    //右子樹深度
    int right = BinaryTreeHigh(root->_left);
    //左子樹深度
    int left = BinaryTreeHigh(root->_right);
    int gap = right - left;
    //深度超過1不是
    if (gap > 1 || gap < -1)
        return 0;
    //遞歸判斷子樹
    return IsBlancedTree_R(root->_left) && IsBlancedTree_R(root->_right);
}

對於上邊的代碼,效率會很低,因爲這種方法存在着許多重複的計算。以上圖的例子分析,從12開始判斷,用BinaryTreeHigh函數求深度時,要遍歷35、9,而在判斷以35位根的樹是否爲平衡二叉樹時也要遍歷9。因此,這種方法存在着許多重複的計算。那麼我們怎麼能讓它們不重複呢?

解決思路二:按照後序遍歷的路線判斷

1.首先,判斷它的左子樹是否爲平衡二叉樹
2.然後在判斷它的右子樹是否爲平衡二叉樹
3.判斷它們是否爲平衡二叉樹的同時,記錄它們的左右子樹的深度
4.最後在判斷以這個結點爲根的樹是否爲平衡二叉樹
代碼實現:

//判斷樹是否爲平衡二叉樹(1:是 0:不是)
//優化版本(不用遍歷重複的結點)
int IsBlancedTree_op(BTNode* root, int *pdepth)
{
    if (root == NULL)
    {
        *pdepth = 0;
        return 1;
    }
    //按照後序遍歷去判斷,先判斷左右子樹,然後記錄以當前結點爲根樹的深度
    int left, right;
    if (IsBlancedTree_op(root->_left, &left) && IsBlancedTree_op(root->_right, &right))
    {
        int gap = right - left;
        if (gap <= 1 && gap >= -1)
        {
            *pdepth = left>right ? left + 1 : right + 1;
            return 1;
        }
    }
    return 0;
}

13.自旋鎖和互斥量的區別

互斥鎖(mutexlock):
最常使用於線程同步的鎖;標記用來保證在任一時刻,只能有一個線程訪問該對象,同一線程多次加鎖操作會造成死鎖;臨界區和互斥量都可用來實現此鎖,通常情況下鎖操作失敗會將該線程睡眠等待鎖釋放時被喚醒。

在多任務操作系統中,同時運行的多個任務可能都需要使用同一種資源。互斥鎖是一種簡單的加鎖的方法來控制對共享資源的訪問,互斥鎖只有兩種狀態,即上鎖( lock )和解鎖( unlock )。

  1. 原子性:把一個互斥量鎖定爲一個原子操作,這意味着操作系統(或pthread函數庫)保證瞭如果一個線程鎖定了一個互斥量,沒有其他線程在同一時間可以成功鎖定這個互斥量;

  2. 唯一性:如果一個線程鎖定了一個互斥量,在它解除鎖定之前,沒有其他線程可以鎖定這個互斥量;

  3. 非繁忙等待:如果一個線程已經鎖定了一個互斥量,第二個線程又試圖去鎖定這個互斥量,則第二個線程將被掛起(不佔用任何cpu資源),直到第一個線程解除對這個互斥量的鎖定爲止,第二個線程則被喚醒並繼續執行,同時鎖定這個互斥量。

自旋鎖(spinlock):
同樣用來標記只能有一個線程訪問該對象,在同一線程多次加鎖操作會造成死鎖;使用硬件提供的swap指令或test_and_set指令實現;同互斥鎖不同的是在鎖操作需要等待的時候並不是睡眠等待喚醒,而是循環檢測保持者已經釋放了鎖,互斥量阻塞後休眠讓出cpu,而自旋鎖阻塞後不會讓出cpu,會一直忙等待,直到得到鎖。這樣做的好處是節省了線程從睡眠狀態到喚醒之間內核會產生的消耗,在加鎖時間短暫的環境下這點會提高很大效率。適用於鎖的持有時間比較短。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章