2.1 面試官談基礎知識
2.2 編程語言
- 程序員寫代碼老是基於某一種編程語言,所以技術面試的時候直接或者間接都會涉及至少一種編程語言。在面試的過程當中,面試官要麼直接問語言的語法,要麼讓應聘者用-~種編程語言寫代碼解決一個問題,經過寫出的代碼來判斷應聘者對他使用的語言的掌握程度。如今流行的編程語言不少,不一樣公司開發用的語言也不盡相同。作底層開發好比常常寫驅動的人更習慣用C, Linux下有不少程序員用C++開發應用程序,基於Windows的C#項目已經愈來愈多,跨平臺開發的程序員則可能更喜歡Java,隨着蘋果iPad、iPhone 的熱銷已經有不少程序員投向了Objective C的陣營,同時還有不少人喜歡用腳本語言如Perl、Python 開發短小精緻的小應用軟件。所以,不一樣公司面試的時候對編程語言的要求也有所不一樣。每一種編程語言均可以寫出一本大部頭的書籍,本書限於篇幅不可能面面俱到。本書中全部代碼都用C/C++/C#實現,下 面簡要介紹一些C++/C#常見的面試題。
面試題1:賦值運算符函數
- 題目:以下爲類型CMyString的聲明,請爲該類型添加賦值運算符函數。
- 思路
-
將返回值類型聲明爲該類型的引用
-
把傳入的參數類型聲明爲常量引用
-
釋放實例自身已有的內存
-
判斷傳入的參數和當前的實例是否是同一個實例
- 不適用java
面試題2:實現Singleton模式
- 題目:設計一個類,咱們只能生成該類的一個實例。
- http://www.javashuo.com/article/p-fpcfqeab-gh.html
- 1. 懶漢模式
- public class SingletonDemo {
- private static SingletonDemo instance;
- private SingletonDemo(){
- }
- public static SingletonDemo getInstance(){
- if(instance==null){
- instance=new SingletonDemo();
- }
- return instance;
- }
- }
- 如上,經過提供一個靜態的對象instance,利用private權限的構造方法和getInstance()方法來給予訪問者一個單例。缺點是,沒有考慮到線程安全,可能存在多個訪問者同時訪問,並同時構造了多個對象的問題。之因此叫作懶漢模式,主要是由於此種方法能夠很是明顯的lazy loading。針對懶漢模式線程不安全的問題,咱們天然想到了,在getInstance()方法前加鎖,因而就有了第二種實現。
- 2. 線程安全的懶漢模式
- public class SingletonDemo {
- private static SingletonDemo instance;
- private SingletonDemo(){
- }
- public static synchronized SingletonDemo getInstance(){
- if(instance==null){
- instance=new SingletonDemo();
- }
- return instance;
- }
- }
- 然而併發實際上是一種特殊狀況,大多時候這個鎖佔用的額外資源都浪費了,這種打補丁方式寫出來的結構效率很低。
- 3. 餓漢模式
- public class SingletonDemo {
- private static SingletonDemo instance=new SingletonDemo();
- private SingletonDemo(){
- }
- public static SingletonDemo getInstance(){
- return instance;
- }
- }
- 直接在運行這個類的時候進行一次loading,以後直接訪問。顯然,這種方法沒有起到lazy loading的效果,考慮到前面提到的和靜態類的對比,這種方法只比靜態類多了一個內存常駐而已。
- 4. 靜態類內部加載
- public class SingletonDemo {
- private static class SingletonHolder{
- private static SingletonDemo instance=new SingletonDemo();
- }
- private SingletonDemo(){
- System.out.println("Singleton has loaded");
- }
- public static SingletonDemo getInstance(){
- return SingletonHolder.instance;
- }
- }
- 使用內部類的好處是,靜態內部類不會在單例加載時就加載,而是在調用getInstance()方法時才進行加載,達到了相似懶漢模式的效果,而這種方法又是線程安全的。
- 本題考點:
-
- 考查對單例(Singleton) 模式的理解。
- 考查對Java的基礎語法的理解,如靜態構造函數等。
- 考查對多線程編程的理解。
2.3 數據結構
數據結構一直是技術面試的重點,大多數面試題都是圍繞着數組、字符串、鏈表、樹、棧及隊列這幾種常見的數據結構展開的,所以每個應聘者都要熟練掌握這幾種數據結構。
數組和字符串是兩種最基本的數據結構,它們用連續內存分別存儲數字和字符。鏈表和樹是面試中出現頻率最高的數據結構。因爲操做鏈表和樹須要操做大量的指針,應聘者在解決相關問題的時候-要留意代碼的魯棒性,不然容易出現程序崩潰的問題。是一個與遞歸緊密相關的數據結構,一樣隊列也與廣度優先遍歷算法緊密相關。深入理解這兩種數據結構能幫助咱們解決不少算法問題。
2.3.1 數組
面試題3:二維數組中的查找
- 測試用例:
-
- 二維數組中包含查找的數字(查找的數字是數組中的最大值和最小值,查找的數字介於數組中的最大值和最小值之間)。
- 二維數組中沒有查找的數字(查找的數字大於數組中的最大值,查找的數字小於數組中的最小值,查找的數字在數組的最大值和最小值之間但數組中沒有這個數字)。
- 特殊輸入測試(輸入空指針)。
- 本題考點:
-
- 考查應聘者對二維數組的理解及編程能力。二維數組在內存中佔據連續的空間。在內存中從上到下存儲各行元素,在同一-行中按照從左到右的順序存儲。所以咱們能夠根據行號和列號計算出相對於數組首地址的偏移量,從而找到對應的元素。
- 考查應聘者分析問題的能力。當應聘者發現問題比較複雜時,能不能經過具體的例子找出其中的規律,是可否解決這個問題的關鍵所在。這個題目只要從一個具體的二維數組的右上角開始分析,就能找到查找的規律,從而找到解決問題的突破口。
2.3.2 字符串
面試題4:替換空格
- 題目:請實現一個函數,把字符串中的每一個空格替換成"%20"。例如輸入「We are happy.",則輸出「We%20are%20happy.」。
- 思路:從後往前複製,數組長度會增長,或使用StringBuilder、StringBuffer類 , 先遍歷空格個數直接擴容
- 代碼實現
- publicclassTestc {
- publicstaticvoidmain(String[] args) {
- System.out.println(replaceSpace(newStringBuffer("We Are Happy.")));
- }
- publicstaticString replaceSpace(StringBuffer str) {
- if(str== null)
- returnnull;
- StringBuilder sb= newStringBuilder();
- for(inti= 0; i< str.length(); i++) {
- if(String.valueOf(str.charAt(i)).equals(" ")) {
- sb.append("%20");
- } else{
- sb.append(str.charAt(i));
- }
- }
- returnString.valueOf(sb);
- }
- }
- 方法二
- "We Are Happy.".replace(" ", "%20")
- 測試用例:
-
- 輸入的字符串中包含空格(空格位於字符串的最前面,空格位於字符串的最後面,空格位於字符串的中間,字符串中有連續多個空格)。
- 輸入的字符串中沒有空格。
- 特殊輸入測試(字符串是個NULL指針、字符串是個空字符串、字符串只有一個空格字符、字符串中只有連續多個空格)。
- 本題考點:
-
- 考查對字符串的編程能力。
- 考查分析時間效率的能力。咱們要能清晰地分析出兩種不一樣方法的時間效率各是多少。
- 考查對內存覆蓋是否有高度的警戒。在分析得知字符串會變長之後,咱們可以意識到潛在的問題,並主動和麪試官溝通以尋找問題的解決方案。
- 考查思惟能力。在從前到後替換的思路被面試官否認以後,咱們能迅速想到從後往前替換的方法,這是解決此題的關鍵。
- 相關題目:
-
- 有兩個排序的數組A1和A2,內存在A1的末尾有足夠多的空餘空間容納A2。請實現一個函數,把A2中的全部數字插入到A1中而且全部的數字是排序的。和前面的例題同樣,不少人首先想到的辦法是在A1中從頭至尾複製數字,但這樣就會出現屢次複製一個數字的狀況。更好的辦法是從尾到頭比較A1和A2中的數字,並把較大的數字複製到A1的合適位置。
- 觸類旁通:
- 合併兩個數組(包括字符串)時,若是從前日後複製每一個數字(或字符)須要重複移動數字(或字符)屢次,那麼咱們能夠考慮從後往前複製,這樣就能減小移動的次數,從而提升效率。
2.3.3 鏈表
咱們說鏈表是一種動態數據結構,是由於在建立鏈表時,無須知道鏈
表的長度。當插入一一個結點時,咱們只須要爲新結點分配內存,而後調整指針的指向來確保新結點被連接到鏈表當中。內存分配不是在建立鏈表時.次性完成,而是每添加一個結點分配一 次內存。因爲沒有閒置的內存,鏈表的空間效率比數組高。
面試題5:從尾到頭打印鏈表
- 題目:輸入一個鏈表的頭結點,從尾到頭反過來打印出每一個結點的值。
- 面試小提示:在面試中若是咱們打算修改輸入的數據,最好先問面試官是否是容許作修改。
-
思路:藉助棧實現,或使用遞歸的方法。
- 代碼實現
- publicArrayList<Integer> printListFromTailToHead(ListNodelistNode) {
- ArrayList<Integer> list= newArrayList<>();
- if(listNode== null)
- returnlist;
- Stack<ListNode> stack= newStack<>();
- while(listNode!= null) {
- stack.push(listNode);
- listNode= listNode.next;
- }
- while(!stack.isEmpty()) {
- list.add(stack.pop().val);
- }
- returnlist;
- }
- 簡單演示 棧
- publicclassTestc {
- publicstaticvoidmain(String[] args) {
- ArrayList<Integer> arr= newArrayList<Integer>();
- arr.add(1);
- arr.add(2);
- arr.add(3);
- arr.add(4);
- arr.add(5);
- printListFromTailToHead(arr);
- }
- publicstaticvoidprintListFromTailToHead(ArrayList<Integer> list) {
- Stack<Integer> stack= newStack<Integer>();
- for(Integer integer: list) {
- stack.push(integer);
- }
- while(!stack.isEmpty()) {
- System.out.println(stack.pop());
- }
- }
- }
- 簡單演示 遞歸
- publicclassTestc {
- publicstaticvoidmain(String[] args) {
- int[] arr= {1,2,3,4,5};
- printListFromTailToHead(arr,0);
- }
- publicstaticvoidprintListFromTailToHead(int[] arr,intnum) {
- if(arr.length> num){
- printListFromTailToHead(arr,num+1);
- System.out.println(arr[num]);
- }
- }
- }
- 測試用例:
- 功能測試(輸入的鏈表有多個結點,輸入的鏈表只有一個結點)。
- 特殊輸入測試(輸入的鏈表頭結點指針爲NULL)。
- 本題考點:
- 考查對單項鍊表的理解和編程能力。
- 考查對循環、遞歸和棧3個相互關聯的概念的理解。
2.3.4 樹
樹是一種在實際編程中常常遇到的數據結構。它的邏輯很簡單:除了根結點以外每一個結點只有一個父結點,根結點沒有父結點;除了葉結點以外全部結點都有一個或多個子結點,葉結點沒有子結點。父結點和子結點之間用指針連接。因爲樹的操做會涉及大量的指針,所以與樹有關的面試題都不太容易。當面試官想考查應聘者在有複雜指針操做的狀況下寫代碼的能力,他每每會想到用與樹有關的面試題。
面試的時候提到的樹,大部分都是二叉樹。所謂二叉樹是樹的一種特殊結構,在二叉樹中每一個結點最多隻能有兩個子結點。在二叉樹中最重要的操做莫過於遍歷,即按照某一-順序訪問樹中的全部結點。一般樹有以下幾種遍歷方式:
- 前序遍歷:先訪問根結點,再訪問左子結點,最後訪問右子結點。圖2.5中的二叉樹的前序遍歷的順序是十、六、四、八、1四、十二、16。
- 中序遍歷:先訪問左子結點,再訪問根結點,最後訪問右子結點。圖2.5中的二叉樹的中序遍歷的順序是四、六、八、十、十二、1四、16。
- 後序遍歷:先訪問左子結點,再訪問右子結點,最後訪問根結點。圖2.5中的二叉樹的後序遍歷的順序是四、八、六、十二、1六、1四、10。
面試題6:重建二叉樹
- 題目:輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹並返回。
-
思路:先找出根節點,而後利用遞歸方法構造二叉樹
- 代碼實現
- classTreeNode {
- intval;
- TreeNode left;
- TreeNode right;
- TreeNode(intx) {
- val= x;
- }
- }
- publicclassTestc {
- publicTreeNode reConstructBinaryTree(int[] pre, int[] in) {
- if(pre== null|| in== null) {
- returnnull;
- }
- if(pre.length== 0 || in.length== 0) {
- returnnull;
- }
- if(pre.length!= in.length) {
- returnnull;
- }
- TreeNode root= newTreeNode(pre[0]);
- for(inti= 0; i< pre.length; i++) {
- if(pre[0] == in[i]) {
- root.left= reConstructBinaryTree(Arrays.copyOfRange(pre, 1, i+ 1), Arrays.copyOfRange(in, 0, i));
- root.right= reConstructBinaryTree(Arrays.copyOfRange(pre, i+ 1, pre.length),
- Arrays.copyOfRange(in, i+ 1, in.length));
- }
- }
- returnroot;
- }
- }
- 測試用例:
- 普通二叉樹(徹底二叉樹,不徹底二叉樹)。
- 特殊二叉樹(全部結點都沒有右子結點的二叉樹,全部結點都沒有左子結點的二叉樹,只有一一個結點的二叉樹)。
- 特殊輸入測試(二叉樹的根結點指針爲NULL、輸入的前序遍歷序列和中序遍歷序列不匹配)。
- 本題考點:
2.3.5 棧和隊列
棧是一個很是常見的數據結構,它在計算機領域中被普遍應用,
好比操做系統會給每一個線程建立-一個棧用來存儲函數調用時各個函數的參數、返回地址及臨時變量等。棧的特色是後進先出,即最後被壓入(push)棧的元素會第一個被彈出(pop)。 在面試題22「棧的壓入、彈出序列」中,咱們再詳細分析進棧和出棧序列的特色。
一般棧是一「個不考慮排序的數據結構,咱們須要O(n)時間才能找到棧中最大或者最小的元素。若是想要在O(1)時間內獲得棧的最大或者最小值,咱們須要對棧作特殊的設計,詳見面試題21「包含min函數的棧」。
隊列是另一種很重要的數據結構。和棧不一樣的是,隊列的特色是先進先出,即第一個進入隊列的元素將會第一個出來。 在2.3.4節介紹的樹的寬度優先遍歷算法中,咱們在遍歷某一層樹的結點時,把結點的子結點放到一個隊列裏,以備下一層結點的遍歷。詳細的代碼參見面試題23「從上到下遍歷二叉樹」。
棧和隊列雖然是特色針鋒相對的兩個數據結構,但有意思的是它們卻相互聯繫。請看面試題7「用兩個棧實現隊列」,同時讀者也能夠考患如何用兩個隊列實現棧。
面試題7:用兩個棧實現隊列
2.4 算法和數據操做
和數據結構同樣,考查算法的面試題也備受面試官的青睞,其中排序和查找是面試時考查算法的重點。在準備面試的時候,咱們應該重點掌握二分查找、歸併排序和快速排序,作到能隨時正確、完整地寫出它們的代碼。
有不少算法均可以用遞歸和循環兩種不一樣的方式實現。一般基於遞歸的實現方法代碼會比較簡潔,但性能不如基於循環的實現方法。在面
試的時候,咱們能夠根據題目的特色,甚至能夠和麪試官討論選擇合適.的方法編程。
位運算能夠當作是一- 類特殊的算法,它是把數字表示成二進制以後對0和1的操做。因爲位運算的對象爲二進制數字,因此不是很直觀,但掌握它也不難,由於總共只有與、或、異或、左移和右移5種位運算。
2.4.1 查找和排序
查找和排序都是在程序設計中常常用到的算法。查找相對而言較爲簡
單,不外乎順序查找、二分查找、哈希表查找和二叉排序樹查找。在試
的時候,無論是用循環仍是用遞歸,面試官都期待應聘者可以信手拈來寫出完整正確的二分查找代碼,不然可能連繼續面試的興趣都沒有。
- 面試小提示:若是面試題是要求在排序的數組( 或者部分排序的數組)中查找一個數字或者統計某個數字出現的次數,咱們均可以嘗試用二分查找算法。
面試題8:旋轉數組的最小數字
- 題目:把一個數組最開始的若干個元素搬到數組的末尾,咱們稱之爲數組的旋轉。 輸入一個非遞減排序的數組的一 個旋轉,輸出旋轉數組的最小元素。 例如數組{3,4,5,1,2}爲{1,2,3,4,5}的一個旋轉,該數組的最小值爲1。 NOTE:給出的全部元素都大於0,若數組大小爲0,請返回0
- 思路:
- 代碼實現
- publicclassTestc {
- publicstaticvoidmain(String[] args) {
- System.out.println(minNumberInRotateArray(newint[] { 1, 0, 1, 1, 1 }));
- }
- publicstaticintminNumberInRotateArray(int[] array) {
- if(array== null|| array.length== 0)
- return0;
- intleft= 0;
- intright= array.length- 1;
- intmid= 0;
- while(array[left] >= array[right]) {
- if(right- left<= 1) {
- mid= right;
- break;
- }
- mid= (left+ right) / 2;
- if(array[left] == array[mid] && array[mid] == array[right]) {
- if(array[left+ 1] != array[right- 1]) {
- intreslut= array[left];
- for(inti= left+ 1; i<= right; i++) {
- if(reslut>array[i]) {
- reslut= array[i];
- }
- }
- returnreslut;
- }
- } else{
- if(array[left] <= array[mid]) {
- left= mid;
- } else{
- right= mid;
- }
- }
- }
- returnarray[mid];
- }
- }
- 測試用例:
- 功能測試(輸入的數組是升序排序數組的一個旋轉,數組中有重複數字或者沒有重複數字)。
- 邊界值測試(輸入的數組是一一個升序排序的數組、只包含一一個數字的數組)。
- 特殊輸入測試(輸入NULL指針)。
- 本題考點:
- 考查對二分查找的理解。本題變換了二分查找的條件,輸入的數組不是排序的,而是排序數組的一個旋轉。這要求咱們對二分查找的過程有深入的理解。
- 考查溝通學習能力。本題面試官提出了一個新的概念:數組的旋轉。咱們要在很短期內學習理解這個新概念。在面試過程當中若是面試官提出新的概念,咱們能夠主動和麪試官溝通,多問幾個問題把概念弄清楚。
- 考查思惟的全面性。排序數組自己是數組旋轉的一一個特例。另外,咱們要考慮到數組中有相同數字的特例。若是不能很好地處理這些特例,就很難寫出讓面試官滿意的完美代碼。
2.4.2 遞歸和循環
若是咱們須要重複地屢次計算相同的問題,一般能夠選擇用遞歸或者循環兩種不一樣的方法。遞歸是在一一個函數的內部調用這個函數自身。而循環則是經過設置計算的初始值及終止條件,在一個範圍內重複運算。
面試小提示:一般基於遞歸實現的代碼比基於循環實現的代碼要簡潔不少,更加容易實現。若是面試官沒有特殊要求,應聘者能夠優先採用遞歸的方法編程。
- 遞歸雖然有簡潔的優勢,但它同時也有顯著的缺點。遞歸因爲是函數調用自身,而函數調用是有時間和空間的消耗的:每一次函數調用,都須要在內存棧中分配空間以保存參數、返回地址及臨時變量,並且往棧裏壓入數據和彈出數據都須要時間。這就不難理解.上述的例子中遞歸實現的效率不如循環。
- 另外,遞歸中有可能不少計算都是重複的,從而對性能帶來很大的負面影響。遞歸的本質是把一一個問題分解成兩個或者多個小問題。若是多個小問題存在相互重疊的部分,那麼就存在重複的計算。在面試題9「斐波那契數列」及面試題43「n個骰子的點數」中咱們將詳細地分析遞歸和循環的性能區別。
- 除了效率以外,遞歸還有可能引發更嚴重的問題:調用棧溢出。前面分析中提到須要爲每一次函數調用在內存棧中分配空間,而每一個進程的棧的容量是有限的。當遞歸調用的層級太多時,就會超出棧的容量,從而致使調用棧溢出。在上述例子中,若是輸入的參數比較小,如10,它們都能返回結果55。但若是輸入的參數很大,如5000,那麼遞歸代碼在運行的時候就會出錯,但運行循環的代碼能獲得正確的結果12502500。
面試題9:斐波那契數列
- 題目一:寫一個函數,輸入n,求斐波那契( Fibonacci )數列的第n項斐波那契數列的定義以下:
- 思路:遞歸實現效率低,循環實現。
- 循環代碼實現
- publicclassTestc {
- publicstaticvoidmain(String[] args) {
- System.out.println(fibonacci(9));
- }
- publicstaticlongfibonacci(intn) {
- longresult= 0;
- longpreOne= 1;
- longpreTwo= 0;
- if(n== 0) {
- returnpreTwo;
- }
- if(n== 1) {
- returnpreOne;
- }
- for(inti= 2; i<= n; i++) {
- result= preOne+ preTwo;
- preTwo= preOne;
- preOne= result;
- }
- returnresult;
- }
- }
- 遞歸代碼實現
- publicclassTestc {
- publicstaticvoidmain(String[] args) {
- System.out.println(fibonacci(9));
- }
- publicstaticlongfibonacci(intn) {
- if(n< 0) {
- return0;
- }
- if(n== 1) {
- return1;
- }
- returnfibonacci(n- 1) + fibonacci(n- 2);
- }
- }
- 題目二:一隻青蛙一次能夠跳上1級臺階,也能夠跳上2級。求該青蛙跳上一個n級的臺階總共有多少種跳法
- 把問題一 0 1 改爲 1 2
- 假設,一級臺階,有f(1)種方法,二級有f(2)種,以此類推,n級有f(n)種方法。
- 能夠看出,f(1)=1;f(2)=2。
- 那麼,假設n級臺階,那麼第一步就有兩種狀況,跳一步,跟跳兩步。
- 狀況一:跳一步,那麼接下去的就是f(n-1);
- 狀況二:跳兩步,那麼接下去的就是f(n-2)。
- 測試用例:
- 功能測試(如輸入三、五、10 等)。
- 邊界值測試(如輸入0、一、2)。
- 性能測試(輸入較大的數字,如40、50、100 等)。
- 本題考點:
- 考查對遞歸、循環的理解及編碼能力。
- 考查對時間複雜度的分析能力。
- 若是面試官採用的是青蛙跳臺階的問題,那同時還在考查應聘者的數學建模能力。
2.4.3 位運算
五種運算:與、或、異或、左移、右移
面試題10:二進制中的1的個數
- 題目:請實現一個函數,輸入一個整數,輸出該數二進制表示中1的個數。例如把9表示成二進制是1001,有2位是1。所以若是輸入9,該函數輸出2。
- 思路:
- 1.可能引發死循環的解法 判斷尾數 右移。面試官接下來可能要問的第二個問題就是:上面的函數若是輸入一個負數,好比0x80000000,運行的時候會發生什麼狀況?把負數0x80000000右移一位的時候 並非簡單地把最高位的1移到第二位變成0x4000000而是0xC000000。這是由於移位前是個負數,仍然要保證移位後是個負數,所以移位後的最高位會設爲1。若是一直作右移運算,最終這個數字就會變成0xFFFFFFFF而陷入死循環。
- 2.爲了不死循環,咱們能夠不右移輸入的數字i。首先把i和1作與運算,判斷i的最低位是否是爲1。接着把1左移一-位獲得2,再和i作與運算,就能判斷i的次低位是否是.....這樣反覆左移,每次都能判斷i的其中一位是否是1。
- 代碼實現
- publicclassTestc {
- publicstaticvoidmain(String[] args) {
- System.out.println(NumberOf(5));
- }
- publicstaticintNumberOf(intn) {
- intcount= 0;
- intflag= 1;
- while(flag!= 0){
- if((n& flag) != 0){
- count++;
- }
- flag= flag<< 1;
- }
- returncount;
- }
- }
- 思路二:把一個整數減去1,再和原整數作與運算,會把該整數最右邊一個1變成0。那麼一一個整數的二進制表示中有多少個1,就能夠進行多少次這樣的操做。
- 代碼實現
- publicclassTestc {
- publicstaticvoidmain(String[] args) {
- System.out.println(NumberOf(7));
- }
- publicstaticintNumberOf(intn) {
- intcount= 0;
- while(n> 0){
- if(n!= 0)
- n= n&(n-1);
- count++;
- }
- returncount;
- }
- }
- 測試用例:
- 正數(包括邊界值一、0x7FFFFFFF)。
- 負數(包括邊界值0x80000000、0xFFFFFFFF)。
- 本題考點:
- 考查對二進制及位運算的理解。
- 考查分析、調試代碼的能力。若是應聘者在面試過程當中採用的是第
- 一種思路,當面試官提示他輸入負數將會出現問題時,面試官會期待他能在心中運行代碼,本身找出運行出現死循環的緣由。這要求應聘者有必定的調試功底。
- 相關題目:
- 用一條語句判斷一「個整數是否是2的整數次方。一個整數若是是2的整數次方,那麼它的二進制表示中有且只有一位是1,而其餘全部位都是0。根據前面的分析,把這個整數減去1以後再和它本身作與運算,這個整數中惟一的1就會變成0。
- 輸入兩個整數m和n,計算須要改變m的二進制表示中的多少位才能獲得n。好比10的二進制表示爲1010, 13 的二進制表示爲1101,須要改變1010中的3位才能獲得1101。咱們能夠分爲兩步解決這個問題:第一步求這兩個 數的異或,第二步統計異或結果中1的位數。
- 觸類旁通:
- 把一個整數減去1以後再和原來的整數作位與運算,獲得的結果至關因而把整數的二進制表示中的最右邊一個1變成0.不少二進制的問題均可以用這個思路解決。
2.5 本章小結
本章着重介紹應聘者在面試以前應該認真準備的基礎知識。爲了應對編程面試,應聘者須要從編程語言、數據結構和算法3方面作好準備。
面試官一般採用概念題、代碼分析題及編程題這3種常見題型來考查應聘者對某一編程語言 的掌握程度。本章的2.2節討論了C++/C#語言這3種題型的常見面試題。
數據結構題目一直是面試官考查的重點。數組和字符串是兩種最基本的數據結構。鏈表應該是面試題中使用頻率最高的一種數據結構。若是面試官想加大面試的難度,他頗有可能會選用與樹(尤爲是二叉樹)相關的第2章面試須要的基礎知識
面試題。因爲棧與遞歸調用密切相關,隊列在圖(包括樹)的寬度優先遍歷中須要用到,所以應聘者也須要掌握這兩種數據結構。
算法是面試官喜歡考查的另一個重點。查找(特別是二分查找)和排序(特別是快速排序和歸併排序)是面試中最常常考查的算法,應聘者必定要熟練掌握。另外,應聘者還要掌握分析時間複雜度的方法,理解即便是同一思路,基於循環和遞歸的不一樣實現它們的時間複雜度可能大不相同。
位運算是針對二進制數字的運算規律。只要應聘者熟練掌握了二進制的與、或、異或運算及左移、右移操做,就能解決與位運算相關的面試題。