前言
坐標:小米base南京,百度base上海,
小米一面8.28
- 深挖專案和競賽
主要是實驗室智能機器人相關的專案(系統設計、機器人視覺、演算法落地);
經典被問為什么研究演算法相關的,作業要找開發(演算法太難了TT);
競賽主要是數學建模(兩次國賽兩次省賽), - 對安卓系統有哪些理解
一開始答的activity運行起來之后的一系列程序,答偏了,面試官想問自己對安卓系統的理解,坦誠沒有思考過,(問點Java基礎吧) - JAVA中的參考型別
- 強參考,任何時候都不會被;垃圾回收器回收,如果記憶體不足,寧愿拋出OutOfMemoryError
使用場景:我們平常大部分使用的場景都是使用了強參考,比如new創建物件,反射獲得一個物件等, - 軟參考,只有在記憶體將滿的時候才會被垃圾回收器回收,如果還有可用記憶體,垃圾回收器不會回收,
軟參考可以和一個參考佇列進行關聯,如果這個軟參考的物件被垃圾回收,就會將這個軟參考加入到關聯的佇列中去, 可用于高速快取, - 弱參考(WeakReference),生命周期更短,只要垃圾回收器運行,就肯定會被回收,不管還有沒有可用記憶體,
使用場景: 弱參考用于生命周期更短的,對記憶體更敏感的場景中,比如占用記憶體很大的Map,java api中就提供了WeakHashMap使用,就會是的大Map被及時清理掉, - 虛參考(PhantomReference),虛參考等于沒有參考,任何時候都有可能被垃圾回收,虛參考必須和參考佇列聯合使用,參考佇列的作用和軟弱參考一樣,
使用場景: 我覺得他的使用場景應該在判斷一個物件是否被垃圾回收了,什么時候參考佇列有新的參考入隊了,就說明他被回收了,
- 強參考,任何時候都不會被;垃圾回收器回收,如果記憶體不足,寧愿拋出OutOfMemoryError
- 堆疊和佇列,應用場景
FILO,FIFO,使用場景答得比較隨意,提了一些堆疊的應用(方法呼叫程序對應入堆疊出堆疊、安卓activity任務堆疊),佇列主要用在一些需要公平處理的場景,訊息佇列,阻塞佇列,
這個問題被問過很多次,每次都是隨意回答一下,希望大佬們評論區指點一波怎么答最好, - 生產者消費者問題中的鎖的傳遞,PV操作
生產者:每次執行時先判斷當前庫存是否超過負載(最大庫存),超過的話就wait,釋放鎖;否則庫存自增,然后喚醒其他執行緒,
消費者:每次執行時先判斷當前庫存是否為零,是的話就wait,釋放鎖;否則庫存自減,然后喚醒其他執行緒,
PV操作當時沒答上來,后來查了一下應該是基于信號量的方式實作消費者生產者問題,因自己不能確保理解正確了,先丟個鏈接Java實作PV操作 ,有大佬理解的可以評論區討論一下! - 宏觀的描述垃圾回收的思路
先判斷哪些物件需要回收,然后根據物件特性確定相應的回收演算法,選用合適的垃圾回收器, - 怎么判斷物件該不該回收,說說自己的理解,如果出現回圈參考怎么辦
參考計數法、可達性分析法 - 可達性分析法中淘汰的物件一定會被回收嗎?
即使在可達性分析演算法中不可達的物件,也并非"非死不可"的,這時候他們暫時處在"緩刑"階段,要宣告一個物件的真正死亡,至少要經歷兩次標記程序: 如果物件在進行可達性分析之后發現沒有與GC Roots相連接的參考鏈,那它將會被第一次標記并且進行一次篩選,篩選的條件是此物件是否有必要執行?nalize()方法,當物件沒有覆寫?nalize()方法或者?nalize()方法已經被JVM呼叫過,虛擬機會將這兩種情況都視為"沒有必要執行",此時的物件才是真正"死"的物件,
如果這個物件被判定為有必要執行?nalize()方法,那么將會被放置在一個叫做F-Queue的佇列之中,并在稍后由一個虛擬機自動建立的、低優先級的Finalizer執行緒去執行它(這里所說的執行指的是虛擬機會觸發?nalize()方法),?nalize()方法是物件逃脫死亡的最后一次機會,稍后GC將對F-Queue中的物件進行第二次小規模標記,如果物件在?nalize()中成功拯救自己(只需要重新與參考鏈上的任何一個物件建立起關聯關系即可,譬如把自己(this關鍵字)賦值給某個類變數或者物件的成員變數),那在第二次標記時它將會被移除出"即將回收"的集合;如果物件這時候還是沒有逃脫,那基本上它就是真的被回收了, - 具體怎么做呢,挑一個垃圾回收演算法談談自己的理解
說了復制演算法, - 復制算有什么問題
僅針對新生代效果好,浪費記憶體(只能用一半)轉移存活物件時會導致用戶執行緒無法定位參考物件, - tcp怎么保證可靠性
- 序列號和確認號機制:
TCP 發送端發送資料包的時候會選擇序列號,接收端收到資料包后會檢測資料包的完整性,如果檢測通過會回應確認號表示收到了資料包, - 超時重發機制:
發送端發送了資料包后會啟動一個定時器,如果一定時間沒有收到接收端的確認,將會重新發送該資料包, - 對亂序資料包重新排序:
從 IP 網路層傳輸到 TCP 層的資料包可能會亂序,TCP 層會對資料包重新排序再發給應用層, - 丟棄重復資料:
從 IP 網路層傳輸到 TCP 層的資料包可能會重復,TCP 層會丟棄重復的資料包, - 流量控制:
TCP 發送端和接收端都有一個固定大小的緩沖空間,為了防止發送端發送資料的速度太快導致接收端緩沖區溢位,發送端只能發送接收端可以接納的資料,為了達到這種控制效果,TCP 用了流量控制協議(可變大小的滑動視窗協議)來實作,
【滑動視窗詳解】
滑動視窗通俗來講就是一種流量控制技術,
它本質上是描述接收方的TCP資料報緩沖區大小的資料,發送方根據這個資料來計算自己最多能發送多長的資料,如果發送方收到接收方的視窗大小為0的話,那么發送方將停止發送資料,等到接收方發送視窗大小不為0的資料報的到來,首次發送資料時的視窗是鏈路帶寬決定, - 擁塞控制:在資料傳輸程序中,可能由于網路狀態的問題,造成網路擁堵,此時引入擁塞控制機制,在保證TCP可靠性的同時,提高性能,具體為慢啟動、擁塞避免、快重傳與快恢復……
- 演算法題:給定一個多叉樹,回傳這棵樹哪一層所有的節點和最大,回傳層號,
本質上就是層序遍歷,維護一個層節點和,多叉樹第一次寫hhh復制代碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
importjava.util.*;publicclassDuochashu {publicstaticvoidmain(String[] args) {TreeNode root =newTreeNode(0);root.children.add(newTreeNode(1));root.children.add(newTreeNode(2));root.children.add(newTreeNode(3));System.out.println(newDuochashu().getMaxLayerVal(root));}privateintgetMaxLayerVal(TreeNode root) {Deque<TreeNode> queue =newLinkedList<>();intmax_layer =0;queue.offer(root);while(!queue.isEmpty()) {intn = queue.size();inttmp =0;for(inti =0; i < n; i++) {TreeNode node = queue.poll();tmp += node.val;for(TreeNode child : node.children) {queue.offer(child);}}max_layer = Math.max(max_layer, tmp);}returnmax_layer;}}classTreeNode {intval;List<TreeNode> children;publicTreeNode() {}publicTreeNode(intval, List<TreeNode> children) {this.val = val;this.children = children;}publicTreeNode(intval) {this.val = val;children =newArrayList<>();}}小結:小米一面是我秋招以來面試中受到鼓勵最強烈的一次,面試官會認真聽我說為什么放棄原來的研究方向選擇做開發,為什么簡歷寫得意向后端但是投了安卓,并且對我的想法表示支持;我在描述自己碩士期間做的課題時他非常耐心,并且表示他作為一個“外行”能夠聽懂這個專案的意義和我做的作業,一個勁的夸我,最后說:作為非科班的學生,我非常看好你!(一面應該給了我非常好的面評,因此最后定了SP)
小米二面9.9
- 為啥要選擇安卓
跟一面面試官問了一樣的問題hhh,經典再現(后面我會單獨整理一份HR面、主管面相關的問題) - 創建執行緒的方式
繼承Thread類;實作Runnable介面;實作Callable介面(JDK1.5);執行緒池方式創建 - 多執行緒的死鎖產生條件
互斥條件:一個資源一次只能被一個執行緒使用
請求與保持條件:一個執行緒因請求資源而阻塞時,對已獲得資源保持不放
不剝奪條件:執行緒獲得的資源,在未完全使用完之前,不能強行剝奪
回圈等待條件:若干行程之間形成一種頭尾相接的環形等待資源關系 - final關鍵字的作用
修飾變數:背final修飾的變數可以當作常量,不能被修改,需要初始化;
修飾方法:方法不能被重寫;
修飾類:類不能被繼承,類的方法也被默認修飾為final - synchronized鎖的作用
使一段代碼塊或者一個方法在多執行緒操作訪問時保證安全,具有原子性、可見性與有序性, - 如果兩個執行緒被synchronized修飾了,執行緒A拿到了鎖,執行緒B會怎么樣?那如果執行緒A這時候阻塞了,執行緒B會怎么樣
(1)A拿到鎖,B阻塞;
(2)A阻塞了,B還是繼續阻塞, - 說說看jvm是啥,有啥用
(答得比較隨意,面試官說別背八股文hhh)他就是來解釋Java原始碼編譯出來的位元組碼檔案的,針對每種OS,JVM有單獨的映射規范來解釋,因此java可以做到跨平臺,JVM負責記憶體里怎么給物件分配空間、怎么回收分配出去的空間…… - 反射有什么用,反射是怎么實作的
盲區,面試后補習了反射相關的知識,
反射就是一種動態獲取類的資訊并呼叫的機制,運行狀態中,對任意一個類,都可以知道它的成員變數與方法,并且可以呼叫,關于怎么實作的,我覺得可以說通過Class.forName()方法獲取類物件,然后通過類物件的newInstance()方法可以創建實體,通過getMethod()方法可以獲取類的成員方法物件,成員方法物件通過invoke()實習呼叫該方法,,不過這么答可能有些淺了,《反射是怎么實作的》求教一波, - 演算法題:合并有序陣列(這道題百度二面也遇到了,小米面試官沒有要求,百度要求只用兩次回圈陳述句)
復制代碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
classSolution {publicvoidmerge(int[] nums1,intm,int[] nums2,intn) {intp1 =0, p2 =0;int[] sorted =newint[m + n];intcur;while(p1 < m || p2 < n) {if(p1 == m) {cur = nums2[p2++];}elseif(p2 == n) {cur = nums1[p1++];}elseif(nums1[p1] < nums2[p2]) {cur = nums1[p1++];}else{cur = nums2[p2++];}sorted[p1 + p2 -1] = cur;}for(inti =0; i != m + n; ++i) {nums1[i] = sorted[i];}}}小結:二面問題還是比較基礎的,不過當時自己困得很,很多應該背熟的八股說的結結巴巴,不過面試官也沒有刁難,全程笑著問,
百度一面9.12(9點開始,持續60min,精神抖擻)
一面純八股(致秋招遇到的第一個開視頻的女面試官溫柔姐姐人美心善帶著口罩愛瞇眼笑)
-
面向物件三大特性,怎么理解多型
繼承 封裝 多型
多型 可以分為兩種:編譯時多型即多載,指java允許方法名相同而引數不同(回傳值可以相同也可以不同),同一個類中允許存在多個同名函式,只要引數型別或引數個數不同即可,
運行時多型即重寫,指在繼承體系中,子類重寫父類方法,JVM運行時根據呼叫該方法的型別決定呼叫那個方法,
Java實作多型的三個必要條件:繼承、重寫和向上轉型:
? 繼承就是多型中必須存在繼承關系的父子類
? 重寫就是子類對父類的某些方法重新定義,
? 向上轉型是說讓父類參考指向子類物件,這樣該參考既可以呼叫父類方法,也可以呼叫子類方法, -
抽象類和介面分別在什么場景使用

-
String是基礎型別還是參考型別
參考型別 -
String物件在進行一個+操作時,會發生什么
運行時, 兩個字串str1, str2的拼接首先會呼叫 String.valueOf(obj),這個Obj為str1,而String.valueOf(Obj)中的實作是return obj == null ? “null” : obj.toString(), 然后產生StringBuilder, 呼叫的StringBuilder(str1)構造方法, 把StringBuilder初始化,長度為str1.length()+16,并且呼叫append(str1)!接下來呼叫StringBuilder.append(str2), 把第二個字串拼接進去, 然后呼叫StringBuilder.toString回傳結果, -
“+”原本是運算子,為什么可以用來拼接字串?
運算子多載,
(這里是有爭議的,Java本身是不支持運算子多載的,String的+操作實際上String類作者設計的語法糖,還可以追問為啥Java不給支持運算子多載?我猜是性能問題) -
new一個物件的背后發生了什么
Java在new一個物件的時候,會先查看物件所屬的類有沒有被加載到記憶體,如果沒有的話,就會先通過類的全限定名來加載,
加載并初始化類完成后,再進行物件的創建作業,我們先假設是第一次使用該類,這樣的話new一個物件就可以分為兩個程序:加載并初始化類和創建物件,
創建物件:
(1)在堆區分配物件需要的記憶體
分配的記憶體包括本類和父類的所有實體變數,但不包括任何靜態變數
(2)對所有實體變數賦默認值
將方法區內對實體變數的定義拷貝一份到堆區,然后賦默認值
(3)執行實體初始化代碼
初始化順序是先初始化父類再初始化子類,初始化時先執行實體代碼塊然后是構造方法
如果有類似于Child c = new Child()形式的c參考的話,在堆疊區定義Child型別參考變數c,然后將堆區物件的地址賦給它 -
java的泛型了解嗎,一般用在什么場景
泛型就是把型別引數化,在編譯的時候才會確定具體的引數,可以用在類、介面、方法中,
場景:我覺得當類 方法 介面 這些 當我們不確定使用的物件的型別是啥 或者 可能存在多種型別的可能的時候,可以使用泛型,最熟悉的就是集合類的實作都用到了泛型,這樣我們在用的時候可以在<>中指定自己的需求,而不針對每種型別設計一個新的類,用上泛型可以提高型別的安全性,避免強轉等,
(有官方回答的求指導) -
程式運行時能夠得到泛型物件的具體型別嗎
不能,編譯的時候型別已經擦除了,看到的都是Object類 -
誰來負責泛型的處理?
答的JVM,她笑了笑,編譯器? -
陣列和list的區別
長度固定與否?可以存參考型別/基礎型別?list實作類有很多,方法很豐富,底層有陣列 有鏈表,又有相應的特點,這題大家應該都會 -
排序演算法的穩定是什么含義?哪些演算法是穩定的
原序列中的值相等的元素的相對順序,排序之后還能保持的,就是穩定,
冒泡 插入 歸并 計數 桶排序…… -
哪些演算法可以做到,每一趟(每一次回圈)都能把某個元素放到它最終應該在的位置?
- 冒泡:每一趟都把最大的冒到最后去
- 選擇排序:取出當前無序序列中最小值與第一位置的元素互換位置
- 快排:每一趟都把比基準小的移到基準左邊去,比基準大的移到基準右邊去,所以基準到了最終位置;
- 堆排序:每一趟回圈后根節點就是最大的,拿它跟末尾元素交換
-
快排每一次回圈干了什么事情,堆排序呢
如上 -
網路分層模型 每一層的功能

-
http在哪一層(應用)
-
http狀態碼302是什么意思(臨時重定向)
-
演算法題:二叉樹的最大深度
復制代碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
importjava.util.*;publicclassMain {publicstaticvoidmain(String[] args) {TreeNode root =newTreeNode(1);root.left =newTreeNode(2);root.left.left =newTreeNode(3);System.out.println(depthOfTree(root));}publicstaticintdepthOfTree(TreeNode root) {if(root ==null) {return0;}returnMath.max(depthOfTree(root.left), depthOfTree(root.right)) +1;}}classTreeNode{intval;TreeNode left;TreeNode right;TreeNode() {}TreeNode(intval) {this.val = val;}}百度二面9.12(10.20開始,持續55min,口干舌燥)
-
String、StringBuilder和StringBuffer的區別
執行速度,在這方面運行速度快慢為:StringBuilder > StringBuffer > String
可變不可變,String為字串常量,而StringBuilder和StringBuffer均為字串變數,即String物件一旦創建之后該物件是不可更改的,但后兩者的物件是變數,是可以更改的,
執行緒安全上,StringBuilder是執行緒不安全的,而StringBuffer是執行緒安全的(String不可變當然執行緒安全) -
什么場景用String,什么場景用StringBuffer
看需求 是否存在執行緒安全問題,空間限制,時間限制 -
JVM怎么判斷物件是否可以回收(可達性分析法)
-
可達性分析法中一般可以選哪些物件作為GC root,常量可以嗎?
虛擬機堆疊(堆疊幀中的本地變數表)中參考的物件,
方法區中靜態屬性參考的物件,
方法區中常量參考的物件,
本地方法堆疊中(Native方法)參考的物件 -
常見的回收演算法,復制演算法的優缺點(不寫了大家應該都會)
-
復制演算法中,使用的空間和未使用的空間比例默認是多少
針對新生代,里面又細分為eden和兩個survivor區,默認8:1:1
后面問了一堆安卓的八股和場景題,答得稀爛,先留個坑 日后再填,,,
-
安卓四大組件
-
為什么要有content provider
-
四大組件有哪些共同點
-
activity的生命周期
-
有一個activity1在運行,這時候來了一個activity2,是一個透明主題界面,再回到activity1,這期間的兩個activity的生命周期狀態是怎么轉換的?
-
安卓開發常見的布局,你用過哪些
-
如果要實作一個滾動界面功能,其中螢屏底部有一個按鈕(如確認)不動,其他內容隨著用戶下滑滾動,怎么做?
-
演算法題1:合并兩個有序鏈表(見小米二面)
-
演算法題2:字串轉整型atoi
復制代碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
importjava.util.*;publicclassSolution {publicintatoi (String str) {// write code herechar[] sc = str.toCharArray();intn = sc.length;intindex =0;while(index < n && sc[index] ==' ') {index++;}if(index == n)return0;intsign =1;charfc = sc[index];if(fc =='+'){index++;}elseif(fc =='-') {index++;sign = -1;}intans =0;while(index < n) {charcur = sc[index];if(cur >'9'|| cur <'0'){break;}if(ans > Integer.MAX_VALUE/10|| (ans == Integer.MAX_VALUE/10&& (cur -'0') > Integer.MAX_VALUE%10)){returnInteger.MAX_VALUE;}if(ans < Integer.MIN_VALUE/10|| (ans == Integer.MIN_VALUE/10&& (cur -'0') > -Integer.MIN_VALUE%10)){returnInteger.MIN_VALUE;}ans = ans*10+ sign*(cur -'0');index++;}returnans;}}
百度三面9.12(11.45開始,持續65min,餓壞了)
- 介紹碩士課題(智能機器人相關)
- 其中的困難、最大的成果、團隊合作、自己的職責
- 安卓專案簡介(做的太基礎,不感興趣)
- 演算法1:搜索插入位置(二分法)
復制代碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
importjava.util.*;publicclassSolution {publicintsearchInsert (int[] A,inttarget) {// write code hereintl =0, r = A.length -1;intmid = -1;while(l <= r) {mid = l + (r-l)/2;if(A[mid] == target){returnmid;}elseif(A[mid] > target){r = mid -1;}else{l = mid +1;}}returnl;}} - 演算法2:最小的K個數
復制代碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
importjava.util.*;publicclassSolution {publicArrayList<Integer> GetLeastNumbers_Solution(int[] input,intk) {ArrayList<Integer> ans =newArrayList<>();if(k ==0)returnans;PriorityQueue<Integer> queue =newPriorityQueue<>(newComparator<Integer>(){//@overridepublicintcompare(Integer o1, Integer o2){returno2 - o1;}});for(inti =0; i < k; i++) {queue.offer(input[i]);}for(inti = k; i < input.length; i++) {if(queue.peek() > input[i]){queue.poll();queue.offer(input[i]);}}for(inti =0; i < k; i++) {ans.add(queue.poll());}returnans;}} - sql:每個人最近的登錄日期(沒做對)
小結:百度的面試整體還是問的比較基礎的,很注重編碼能力,三輪連環面,從9點到下午1點,,,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/348377.html
標籤:其他
下一篇:C語言實作佇列
