面試題1:賦值運算符重載:該題主要考察 拷貝構造,構造析構,重載操做符。在面試者使用 c++ 等語言時進行考察。c++
面試題2:實現Singleton模式:懶漢線程不安全,餓漢線程安全(可是不能延遲加載),雙重檢查鎖定+volatile關鍵字 (能夠實現線程安全,而且能夠延遲加載)git
面試題3:二維數組中的查找:對於在一個每一行從左到右依次遞增,每一列從上到下依次遞增的二維數組查找一個元素,能夠選擇從數組左上角開始查找array[i][j],若是目標元素大於array[i][j],i+=1,若是元素小於array[i][j],j-=1,依次循環直至找到這個數。github
面試題4:替換空格:若是直接每次遇到空格添加'%20',那麼空格後面的數字就須要頻繁向後移動。遇到這種移動問題,咱們能夠嘗試先給出最終須要的長度,而後從後向前掃描,同時給定兩個指針來保證定位。「逆向思惟」面試
面試題5:從頭至尾打印鏈表:從頭至尾遍歷鏈表,並用一個棧存儲每一個結點的值,以後出棧輸出值便可。正則表達式
面試題6:重建二叉樹:利用二叉樹前序遍歷和中序遍歷的特性。前序遍歷的第一個值必定爲根節點,對應於中序遍歷中間的一個點。在中序遍歷序列中,這個點左側的均爲根的左子樹,這個點右側的均爲根的右子樹。這時能夠利用遞歸,分別取前序遍歷[1:i+1]和中序遍歷的[:i]對應與左子樹繼續上一個過程,取前序遍歷[i+1:]和中序遍歷[i+1]對應於右子樹繼續上一個過程,最終得以重建二叉樹。算法
面試題7:用兩個棧實現隊列:須要兩個棧Stack1和Stack2,push的時候直接push進Stack1。pop須要判斷Stack1和Stack2中元素的狀況,Stack1空的話,直接從Stack2 pop,Stack1不空的話,把Stack1的元素push進入Stack2,而後pop Stack2的值。推廣:用兩個隊列實現棧數組
面試題8:旋轉數組的最小數字:二分查找的變形,注意到旋轉數組的首元素確定不小於旋轉數組的尾元素,設置中間點。若是中間點大於首元素,說明最小數字在後面一半,若是中間點小於尾元素,說明最小數字在前一半。依次循環。同時,當一次循環中首元素小於尾元素,說明最小值就是首元素。可是當首元素等於尾元素等於中間值,只能在這個區域順序查找。安全
面試題9:斐波那契數列:如何不使用遞歸實現斐波那契數列,須要把前面兩個數字存入在一個數組中。斐波那契數列的變形有不少,如青蛙跳臺階,一次跳一個或者兩個;鋪瓷磚問題。「變態青蛙跳」,每次至少跳一個,至多跳n個,一共有f(n)=2n-1種跳法。考察數學建模的能力。app
面試題10:二進制中1的個數:注意到每一個「非零」整數n和n-1進行按位與運算,整數n的二進制數中最右邊的1就會變成0,那麼二進制數中的1的個數就會減小一個,所以能夠利用一個循環,使得 n = n&(n-1) ,計算通過幾回運算減小到0,就是有幾個1。注意:書中給了另外兩種方法,分別是原始n左移一位和右移一位的方法,由於Python不會出現整數溢出的狀況,這裏就再也不考慮着兩種方法。擴展:判斷一個數值是否是2得整數次方,若是是的話,這個數的二進制數中有且只有一個1,那麼這個數n會有 n&(n-1) == 0。或者求兩個整數m和n須要改變m二進制中的多少位才能獲得n,能夠先作 m^n 的異或運算,而後求這個數中有多少個1。dom
面試題11:數值的整數次方:若是採用常規解法,須要注意的地方:當指數爲負數的時候;當底數爲零且指數爲負數的狀況;在判斷底數base是否是等於0的時候,不能直接寫base==0, 由於計算機內表示小數時有偏差,只能判斷他們的差的絕對值是否是在一個很小的範圍內。若是採用遞歸解法,當n爲偶數, an = an/2 an/2,當n爲奇數, an = a(n-1)/2 a(n-1)/2 * a,利用右移一位代替除2運算,利用 &1 判斷是否爲奇數。同時須要注意「遞歸終止條件」,exponent = 1的話,return base,exponent = -1的話,return 1.0/base。再次提醒!必須寫成 1.0/base,不然 1/base,返回一個integer 0!
面試題12:打印1到最大的n位數:該題的要點是注意輸入的n位數是否會致使溢出,所以利用字符串模擬整數的加法。「注意」:在打印函數中,須要判斷打印的數字是不是以0開頭的,同時判斷條件是 num[i] != "0",不能寫做 num[i] != 0,由於是使用str類型的,後面一種寫法致使判斷沒法成功。
面試題13:在O(1)時間刪除鏈表結點:當要刪除的結點不是尾結點並且不是僅有一個結點的頭結點,能夠把該結點i的下一個結點j的內容複製到結點i,同時把i結點的next指向j結點的next,而後再刪除結點j。若是要刪除的鏈表爲單結點鏈表且待刪除的結點就是頭結點,須要把頭結點置爲None,若是刪除的結點爲鏈表的尾結點,那麼就須要順序遍歷鏈表,找到尾節點前面一個結點,而後將其next置空。
面試題14:調整數組順序使奇數位於偶數前面:注重函數的擴展性能。把函數中的判斷條件寫成一個判斷條件的函數,方便與函數的擴展。對於奇數位於偶數前面的狀況,相似於快排,在頭和尾分別設置一個指針,頭指針指向奇數則後移,尾指針指向偶數則前移。
面試題15:鏈表中倒數第k個結點:代碼的魯棒性。須要注意:若是輸入的鏈表爲空;k大於鏈表的長度;k爲0的狀況。對於正常狀況,設置兩個指針分別指向頭結點,第一個指針向前走「k-1步」,走到正數第k個結點,同時保持第二個指針不動,而後第一個指針和第二個指針每次同時前移一步,這樣第一個指針指向尾結點的時候,第二個指針指向倒數第k個結點。判斷尾結點的條件是 「pNode.next == None」。
面試題16:遞歸以及非遞歸實現反轉鏈表:須要注意三個問題:輸入的鏈表頭指針爲None或者整個鏈表只有一個結點時,反轉後的鏈表出現斷裂,返回的翻轉以後的頭節點不是原始鏈表的尾結點。所以須要引入一個翻轉後的頭結點,以及一個指向當前結點的指針,一個指向當前結點前一個結點的指針,一個指向當前結點後一個結點的指針,防止出現斷裂。推廣:遞歸實現反轉鏈表
面試題17:合併兩個排序的鏈表:要注意特殊輸入,若是輸入是空鏈表,不能崩潰。
面試題18:樹的子結構:多出須要判斷指針是否是None,避免訪問空指針而形成程序崩潰。
面試題19:二叉樹的鏡像:須要判斷輸入的結點爲空或者輸入的結點沒有子樹的狀況。
面試題20:順時針打印矩陣:首先須要判斷每一步開始是的座標點是否知足小於行數的一半且小於列數的一半,在最後一圈中,可能出現僅能向右走一行,僅能向右走一行向下走一列,向右走一行向下走一列向左走一行,能走完整一圈,一共四種狀況。其中只有能向左走一行必然發生,沒必要判斷,剩餘的都須要判斷髮生條件。
面試題21:包含min函數的棧:引入兩個棧,一個棧每次push實際的數字,另外一個minStack,若是push的數字小於minStack棧頂的數字,push新的數字,繁殖,把棧頂的數字再壓入一遍。
面試題22:棧的壓入、彈出序列:創建一個輔助棧,把push序列的數字依次壓入輔助棧,每次壓入後,比較輔助棧的棧頂元素和pop序列的首元素是否相等,相等的話就推出pop序列的首元素和輔助棧的棧頂元素,若最後輔助棧爲空,則push序列能夠對應於pop序列。
面試題23:從上往下打印二叉樹:引入一個隊列便可。推廣:有向圖的廣度優先遍歷也是基於隊列的。
面試題24:二叉搜索樹的後續遍歷序列:根據後續遍歷的性質,尾元素一定是樹的根,同時小於尾元素的值是左子樹,大於尾元素的值爲右子樹,且序列前半部分均小於尾元素,後半部分均大於尾元素(若是同時存在左右子樹的話),能夠將序列劃分左子樹序列和右子樹序列,而後遞歸比較師妹每一段均知足此性質。能夠減小遞歸深度的辦法:某段的元素個數若是<=3,則返回True;某整段的最小元素不小於尾元素或者整段的最大元素不大於尾元素,說明僅有左子樹或者右子樹,返回True。
面試題25:二叉樹中和爲某一值的路徑:遞歸
面試題26:複雜鏈表的複製:注意鏈表結點進行復制的時候,不能簡單地寫做 pCloned = pNode,這樣的話以後對pCloned的操做也會做用在pNode上面,致使操做循環往復。須要從新定一個pCloned = ListNode(0),而後對結點的.val .next .random 進行設置。同時,在將複製的結點的random指向原始鏈表結點的random的next的時候,須要先判斷一下,原始鏈表結點的next是否爲None,不爲None再指向。
面試題27:二叉搜索樹與雙向鏈表:按照左右子樹分治,遞歸實現。根的左邊鏈接左子樹的最右邊結點,右邊鏈接右子樹的最左邊結點。
面試題28:字符串的排列:依次取一個元素,而後依次和以前遞歸造成的全部子串組合,造成新的字符串。擴展:字符串的組合
面試題29:數組中出現次數超過一半的數字:兩種思路。第一種思路,出現次數超過一半的數字,無論如何,必然這個數字位於數組中間的位置,所以能夠採用相似於快排的劃分的方法,找到位於數組中間的位置的數字,而後在順序檢索是否這個數字出現次數超過一半。第二種思路根據數組的特色,出現次數超過一半的數,他出現的次數比其餘數字出現的總和還要多,所以能夠最開始保存兩個數值:數組中的一個數字以及它出現的次數,而後遍歷,若是下一個數字等於這個數字,那麼次數加一,若是不等,次數減一,當次數等於0的時候,在下一個數字的時候從新複製新的數字以及出現的次數置爲1,直到進行到最後,「而後再驗證最後留下的數字是否出現次數超過一半」,由於可能前面的次數依次抵消掉,最後一個數字就直接是保留下來的數字,可是出現次數不必定超過一半。
面試題30:最小的k個數:兩種方法。第一種方法是基於劃分的方法,若是是查找第k個數字,第一次劃分以後,劃分的位置若是大於k,那麼就在前面的子數組中進行繼續劃分,反之則在後面的子數組繼續劃分,時間複雜度O(n);第二種方法是能夠適用於「海量數據」的方法,該方法基於二叉樹或者堆來實現,首先把數組前k個數字構建一個最大堆,而後從第k+1個數字開始遍歷數組,若是遍歷到的元素小於堆頂的數字,那麼久將換兩個數字,從新構造堆,繼續遍歷,最後剩下的堆就是最小的k個數,時間複雜度O(nlog k)。
面試題31:連續子數組的最大和:關鍵的問題在於成功分析整個過程。對於連續子數組,能夠用一個數值來存儲當前和,若是當前和小於零,那麼在進行到下一個元素的時候,直接把當前和賦值爲下一個元素,若是當前和大於零,則累加下一個元素,同時用一個maxNum存儲最大值並隨時更新。也能夠利用動態規劃解決。
面試題32:從1到n整數中1出現的次數:利用數字規律實現更爲簡單。
面試題33:把數組排成最小數:首先將數組中的數字所有轉換爲字符串存儲在一個新的數組中,而後比較每兩個數字串的拼接的mn和nm的大小,若mn<nm,則m更小,反之n更小,而後把更小的數放入一個新的List中,最後輸出便可。使用冒泡排序很方便。
面試題34:醜數:空間換時間。創建一個長度爲n的數組,保存這n個醜數。在進行運算的時候,某個位置須要求得醜數必定是前面某個醜數乘以二、3或者5的結果,咱們分別記錄以前乘以2後能獲得的最大丑數M2,乘以3後能獲得的最大丑數M3,乘以5後能獲得的最大丑數M5,那麼下一個醜數必定是M2,M3,M5中的最小的那一個。同時注意到,已有的醜數是按順序存放在數組中的。對乘以2而言,確定存在某一個醜數T2,排在他以前的每個醜數乘以2獲得的結果都會小於已有的最大丑數,在他以後的每個醜數乘以2獲得的結果都會太大,咱們只需記下這個醜數的位置,每次生成新的醜數的時候,去更新這個T2。對於3和5同理。
面試題35:第一個只出現一次的字符:先遍歷一遍字符串,用一個hash表存放每一個出現的字符和字符出現的次數。再遍歷一遍字符串,找到hash值等於1的輸出便可。
面試題36:數組中的逆序對:這道題能夠這麼想,咱們要找到數組中的逆序對,能夠看作對數據進行排序,須要交換數組中的元素的次數,可是防止相同大小的元素髮生交換,所以須要選擇一個穩定的排序方法,記錄發生交換的次數。那麼,基於比較的穩定的排序方法中,最快的方法就是歸併了,因此直接按照歸併排序的思路,將數組分解、合併、排序便可。可是須要注意的是,在常規歸併排序的時候,若是前一個元素大於後一個元素,直接進行交換便可,只進行了一次操做,可是對於這道題來說,對於每一次的歸併段,咱們選擇從後向前遍歷,前面的歸併段的某一個數值left[i]若是大於後面的某一個數值right[j],由於在right本身獨自排序的過程當中,已經保證了right是有序的,因此j位置前面的數字所有小於right[j],因此在這裏逆序對的個數就會是 j-start-length,其中start是整個數組的起點,length是left的長度,而後再進行交換。
面試題37:兩個鏈表的第一個公共結點:首先依次遍歷兩個鏈表,記錄兩個鏈表的長度m和n,若是 m > n,那麼咱們就先讓長度爲m的鏈表走m-n個結點,而後兩個鏈表同時遍歷,當遍歷到相同的結點的時候中止便可。對於 m < n,同理。
面試題38:數字在排序數組中出現的次數:二分查找的擴展。能夠構造兩個函數。第一個函數查找目標數字出現的最前面的位置,先使用二分查找找到該數字,若是該數字的index > 0並且該數字前面一個數字等於k的話,那麼就令end=middle-1,繼續二分查找。對於第二個函數,查找目標數字出現的最後面的位置,反之編寫。最後若是「數字存在」的話,令走後面的index減去最前面的index而後+1便可。「在進行有序數組的元素查找,能夠先嚐試一下二分查找」
面試題39:二叉樹的深度:利用遞歸實現。若是一棵樹只有一個結點,那麼它的深度爲1。遞歸的時候無需判斷左右子樹是否存在,由於若是該節點爲葉節點,它的左右子樹不存在,那麼在下一級遞歸的時候,直接return 0。同時,記得每次遞歸返回值的時候,深度加一操做。
面試題39:判斷平衡二叉樹:基於二叉樹的深度,再次進行遞歸。以此判斷左子樹的高度和右子樹的高度差是否大於1,如果則不平衡,反之平衡。
面試題40:數組中只出現一次的數字:「任何一個數字異或他本身都等於0」,「0異或任何一個數都等於那個數」。數組中出了兩個數字以外,其餘數字都出現兩次,那麼咱們從頭至尾依次異或數組中的每一個數,那麼出現兩次的數字都在整個過程當中被抵消掉,那兩個不一樣的數字異或的值不爲0,也就是說這兩個數的異或值中至少某一位爲1。咱們找到結果數字中最右邊爲1的那一位i,而後一次遍歷數組中的數字,若是數字的第i位爲1,則數字分到第一組,數字的第i位不爲1,則數字分到第二組。這樣任何兩個相同的數字就分到了一組,而兩個不一樣的數字在第i位必然一個爲1一個不爲1而分到不一樣的組,而後再對兩個組依次進行異或操做,最後每一組獲得的結果對應的就是兩個只出現一次的數字。
面試題41:和爲s的兩個數字:設定兩個指針,一個指向數組的起點,一個指向數組的終點,而後對兩個數字求和,若是和大於目標值,則把後一個指針前移,若是和小於目標值,則把前一個指針後移。兩個指針交匯的時候若是還沒找到,就終止操做。
面試題42:和爲s的連續正數序列:設定兩個指針,先分別指向數字1和數字2,並設這兩個指針爲small和big,對small和big求和,若是和大於目標值,則從當前和中刪除small值,並把small值加一,若是和小於目標值,則把big值加一,再把新的big值加入和中。若是和等於目標值,就輸出small到big的序列,同時把big加一併加入和中,繼續以前的操做。
面試題43:翻轉單詞順序:首先須要寫一個reverse函數,把任何輸入的字符串徹底翻轉。而後從前日後依次遍歷新字符串,若是遇到空格,就把空格前的字符串用reverse翻轉,添加空格,繼續遍歷。須要注意的是,若是新字符串結尾不是空格,當遍歷到結尾的時候,前一個空格到結尾的字符串沒有翻轉,所以記得跳出遍歷後,須要再完成一次翻轉操做。
面試題44:左旋轉字符串:首先須要寫一個reverse函數,把任何輸入的字符串徹底翻轉。而後根據題目中給出的左旋轉字符串的個數n,用全字符串長度length減去旋轉字符串個數n,求得對於新的字符串應該在哪一位進行旋轉,而後分別旋轉前[:length-n]子串和[length-n:]子串,從新拼接兩個子串便可。
面試題45:n個骰子的點數:用兩個數組來存儲骰子點數的每個總數出現次數。在一次循環中,第一個數組中的第n個數字表示骰子和爲n出現的次數。在下一次循環中加入一個新的骰子,此時和爲n的骰子出現的次數應該等於上一次循環中骰子點數和爲n-1,n-2,n-3,n-4,n-5,n-6的次數的總和,也就是把另外一個數組的第n個數字對應上一個數組的n-1,n-2,n-3,n-4,n-5,n-6的次數的總和。同時須要注意的是,「每次使用新數組的時候,須要把數組全部位置清零」,由於咱們對於第n位進行的累加操做,若是以前第n位有數字但不清零的話,會致使結果偏大。
面試題46:撲克牌的順子:先置換特殊字符AJQK爲數字,排序,而後求出大小王即0的個數,而後求出除去0以外的,數組間的數字間隔(求間隔的時候記得減去1,好比4和5的間隔爲5-4-1,表示4和5是連續的數字),同時求間隔的時候須要鑑別是否出現對。最後比較0的個數和間隔的大小便可。
面試題47:圓圈中剩下的數字:遞推公式:f[i] = (f[i-1]+m)%i。詳解
面試題48:求1+2+...+n:利用兩個函數,一個函數充當遞歸函數的角色,另外一個函數處理終止遞歸的狀況。若是對n連續進行兩次反運算,那麼非零的n轉換爲True,0轉換爲False。利用這一特性終止遞歸。注意考慮測試用例爲0的狀況。
面試題49:不用加減乘除作加法:將兩個數的加法看做兩步,第一步是兩個數相加可是不進位,第二步是記錄以前的兩數相加應該進位的地方加上前一個相加可是不進位的數。對於具體的兩個不小於0的數m和n,第一步能夠看作m和n的異或運算m^n,第二步能夠看作m和n的與運算而後左移一位獲得實際的進位位置(m&n)<<1。而後把兩個獲得的數字加起來繼續操做,指到carry進位爲0終止操做。對於含有負數的狀況,見博文。
面試題50:把字符串轉換成整數:主要是區分輸入和合法性,好比輸入一個None,輸入一個空字符串 "",或者輸入的字符串中含有「+」或者「-」,或者輸入的字符串中含有除去+ — 數字的非數字字符,如何段應正常的輸出仍是報錯,須要考慮的全面一些。
面試題51:樹中兩個節點的最低公共祖先:首先來看比較簡單的狀況--二叉搜索樹的最低公共祖先,對於二叉搜索樹而言,每一個節點的左子節點都小於這個數,右子節點都大於這個數,所以,咱們比較當前節點和須要比較的結點m,n的大小,若是當前節點的值均大於m,n,則在當前節點的左子樹繼續操做,若是當前節點均小於m,n,則在當前節點的右子樹繼續操做,反之,則當前結點是最小公共祖先。而對於普通的二叉樹而言,咱們若是但願找到兩個結點的最低公共祖先,那麼咱們能夠先從樹的根節點開始,找到根節點到結點m和結點n的路徑,這時候咱們就有兩個List或者兩個鏈表,而後就像前面題中遇到的尋找兩個鏈表的公共結點同樣,從後往前遍歷兩個List找到最靠後的第一個公共結點便可。
面試題52:數組中重複的數字:對於一個長度爲n的數組裏全部的數字都在0到n-1的範圍內。查找重複數字的話,首先容易想到,對數組進行排序,而後遍歷數組查找重複的數字,這樣的時間複雜度爲O(nlogn);或者創建一個哈希表,這樣實在O(n)的時間查找到,可是空間複雜度O(n)。另一個空間複雜度爲O(1)的算法以下,由於數字在0~n-1的範圍內,那麼若是數字沒有重複,那麼當數組排序以後數字i將出如今下標爲i的位置,可是有重複的話,在某個位置j出現的數字將不是j。咱們重排這個數組。從頭至尾依次掃描這個數組中的每一個數字,若是下標i不是出現數字i,那麼就把數字i和i處的數字進行交換使數字i出如今應該出現的位置,若是新交換的數字還不是他應該出現的位置,繼續交換,直至該處的數字m等於x下標m,若是在交換的過程當中,第i處的位置數字等於第m處的數字,那麼咱們就找到了第一個重複的數字,記錄這個數字,在從下一個位置繼續掃描。
面試題53:構建乘積數組:做圖畫出一個n*n的矩陣,便可看出規律。注意須要獲得的向量初始化的時候,初始化的值應該爲1。
面試題54:正則表達式匹配:這道題的關鍵在於縷清思路。具體狀況分析看一下代碼中的註釋。
面試題55:表示數值的字符串:這道題的關鍵也在於討論清楚狀況,把全部可能出現的狀況都考慮到。須要注意的是,指數E後面必須跟一個整數,不能沒有數,也不能爲小數。
面試題56:字符流中第一個不重複的字符:引入兩個輔助存儲空間。一個Dict存儲當前出現的字符以及字符出現的次數,一個List存儲當前出現字符。而後每次比較List的第一個字符在Dict中對應的次數,若是爲1則輸出這個字符,若是不爲1則彈出這個字符比較下一個字符。
面試題57:鏈表中環的入口結點:尋找鏈表中環的入口結點主要分紅三個步驟:首先是設置兩個快慢指針,若是快慢指針相遇,則快慢指針必然都在環中;而後從相遇的地方設置一個指針向後遍歷並記錄走的步數,當這個指針從新指到開始的位置的時候,當前對應的步數就是環中結點的數量k;而後設置兩個指針從鏈表開始,第一個節點先走k步,而後第二個指針指到鏈表的開始,兩個指針每次都向後走一步,兩個指針相遇的位置就是鏈表的入口。
面試題58:刪除鏈表中重複的結點:咱們須要設置一個指針preNode,preNode最開始爲None,而後設置兩個指針,pNode指向當前節點,pNext指向pNode下一個結點,⓵若是pNext不爲空並且pNext的值等於pNode的值,那麼就說明出現了重複數字的結點,就須要刪除,而後從pNode開始遍歷,若是結點值等於前面那個重複值,繼續遍歷。當遍歷到None或者不一樣值結點的時候,這時候須要判斷preNode結點,若是preNode結點爲None,就說明咱們剛纔的重複結點是從整個鏈表的頭結點開始重複的,就直接把pHead設置爲當前結點,pNode也設置爲當前結點。反之,若是preNode不爲None,直接把preNode的下一個指針指向當前節點,pNode指向preNode便可;⓶若是pNext爲空或者pNext的值不等於pNode的值,說明當前的這個pNode和後面的值不重複,直接令preNode = pNode,pNode指向下一個結點便可。
面試題59:二叉樹的下一個結點:三種狀況:當前節點有右子樹的話,當前節點的下一個結點是右子樹中的最左子節點;當前節點無右子樹可是是父節點的左子節點,下一個節點是當前結點的父節點;當前節點無右子樹並且是父節點的右子節點,則一直向上遍歷,直到找到最靠近的一個祖先節點pNode,pNode是其父節點的左子節點,那麼輸入節點的下一個結點就是pNode的父節點。
面試題60:對稱的二叉樹:分爲遞歸和非遞歸的兩種方式,思想是同樣的。主要就是把葉子節點的None節點也加入到遍歷當中。按照前序遍歷二叉樹,存入一個序列中。而後按照和前序遍歷對應的先父節點,而後右子節點,最後左子節點遍歷二叉樹,存入一個序列。若是先後兩個序列相等,那麼說明二叉樹是對稱的。
面試題61:把二叉樹打印成多行:引入兩個隊列。首先把當前層的節點存入到一個隊列queue1中,而後遍歷當前隊列queue1,在遍歷的過程當中,若是節點有左子樹或右子樹,依次存入另外一個隊列queue2。而後遍歷隊列queue2,如此往復。
面試題62:按之字形順序打印二叉樹:按之字形順序打印二叉樹須要兩個棧。咱們在打印某一行節點時,拔下一層的子節點保存到相應的棧裏。若是當前打印的奇數層,則先保存左子節點再保存右子節點到第一個棧裏;若是當前打印的是偶數層,則先保存右子節點再保存左子節點到第二個棧裏。
面試題63:序列化二叉樹:最終要實現的是二叉樹的序列化和反序列化。首先來看二叉樹的序列化,二叉樹的序列化就是採用前序遍歷二叉樹輸出節點,再碰到左子節點或者右子節點爲None的時候輸出一個特殊字符"#"。對於反序列化,就是針對輸入的一個序列構建一棵二叉樹,咱們能夠設置一個指針先指向序列的最開始,而後把指針指向位置的數字轉化爲二叉樹的結點,後移一個數字,繼續轉化爲左子樹和右子樹。當遇到當前指向的字符爲特殊字符"#"或者指針超出了序列的長度,則返回None,指針後移,繼續遍歷。
面試題64:二叉搜索樹的第k個結點:中序遍歷輸出一個序列,而後找到序列中第k個數便可。
面試題65:數據流中的中位數:構建一個最大堆和一個最小堆,分別存儲比中位數小的數和大的數。當目前兩堆總數爲偶數的時候,把數字存入最大堆,而後重排最大堆,若是最大堆的堆頂數字大於最小堆堆頂數字,則把兩個堆頂數字交換,重排兩堆,此時兩堆數字總數爲奇數,直接輸出最大堆堆頂數字即爲中位數;若是當前兩堆總數爲技術的時候,把數字存入最小堆,重排最小堆,若是最大堆的堆頂數字大於最小堆堆頂數字,則把兩個堆頂數字交換,重排兩堆,此時兩堆數字總數爲偶數,取兩堆堆頂數字作平均即爲中位數。
面試題66:滑動窗口的最大值:咱們把可能成爲滑動窗口的最大值的數值下標存入一個兩端開口的隊列index中。首先遍歷輸入數組,在遍歷次數小於窗口長度的時候,若是index數組裏面含有元素並且元素後面的下標值對應的輸入數組的數若是小於當前遍歷到的輸入數組元素值,那麼就把尾部的元素下標值不斷pop出來,再壓入當前輸入元素對應的下標值。而後再從等於滑動窗口大小的位置繼續遍歷輸入數組。首先把index數組的頭元素下標值對應輸入數組值壓入輸出數組。一樣的,若是index數組裏面含有元素並且元素後面的下標值對應的輸入數組的數若是小於當前遍歷到的輸入數組元素值,那麼就把尾部的元素下標值不斷pop出來,同時,若是index數組內有元素,並且當一個數字的下標與當前處理的數字的下標只差大於或等於滑動窗口的大小時,這個數字已經從窗口中畫出,能夠從隊列中刪除了,再壓入當前輸入元素對應的下標值。「最後還須要在輸出數組中append一下index手元素下標對應的輸入元素值」。
面試題67:矩陣中的路徑:回溯法。任選一個格子做爲路徑的起點。假設矩陣中某個格子的字符爲ch而且這個格子將對應於路徑上的第i個字符。若是路徑上的第i個字符不是ch,那麼這個格子不可能處在路徑上的第i個位置。若是路徑上的第i個字符正好是ch,那麼往相鄰的格子尋找路徑上的第i+1個字符。除在矩陣邊界上的格子外,其餘各自都有4個相鄰的格子。重複這個過程直到路徑上的全部字符都在矩陣中找到相應的位置。
面試題68:機器人的運動範圍:回溯法。相似於面試題66。把方格當作一個m*n的矩陣,從(0,0)開始移動。當準備進入座標(i, j)是,經過檢查座標的數位來判斷機器人可否進入。若是能進入的話,接着判斷四個相鄰的格子。
面試題69:八皇后問題:使用回溯法依次假設皇后的位置,當第一個皇后肯定後,尋找下一行的皇后位置,當知足左上、右上和正上方向無皇后,即矩陣中對應位置都爲0,則能夠肯定皇后位置,依次判斷下一行的皇后位置。當到達第8行時,說明八個皇后安置完畢。
本文參考自:《劍指offer》 和 https://github.com/Jack-Lee-Hiter/AlgorithmsByPython
本文學習須要必定基礎。建議收藏起來,在題目完成後進行鞏固。
我把我寫的全部題解整理成了一本電子書放在了 github 上,三天內衝擊到 github 排行榜榜首!近 5w 人下載閱讀!要獲取的話,直接進入下方連接就能夠了(記得給我點個 star):