劍指Offer編程題

 1.題目:二維數組中的查找

    在一個二維數組中,每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函數,輸入這樣的一個二維數組和一個整數,判斷數組中是否含有該整數。

解法:從二維數組的左下角開始比較,令 i = n - 1 , j = 0;(假設數組爲a,i爲要比較的行號,j爲列號),當目標值與a[i][j],比較的時候,如果等於目標值則結束,如果目標值小於a[i][j],則 i--,否則 j++,注意 i 和 j 的範圍限制。

代碼實現

2.題目:替換空格

    請實現一個函數,將一個字符串中的空格替換成“%20”。例如,當字符串爲We Are Happy.則經過替換之後的字符串爲We%20Are%20Happy。

解法:本題是在一個數組上完成的替換,數組長度滿足要求,首先設置兩個指針,p1 ,p2 ,p1指向原先數組中的最後一個字符的位置,p2指向經過計算後,處理完成時最後一個字符的指針,然後以p1爲主,先判斷p1是否是空格,如果是,將“02%”(注意是倒着來)複製到p2,p2-1,p2-2對應的位置中,注意p2指針的處理,如果p1所指的字符不是空格,那就將值複製到p2所指的位置,p2--,一直這樣執行,直到p1 == p2就結束。

代碼實現

3.題目:從頭到尾打印鏈表  

    輸入一個鏈表,從尾到頭打印鏈表每個節點的值。

    解法:遍歷鏈表將值輸入到vector裏,然後利用reverse翻轉vector。

代碼實現

4.題目:重建二叉樹

    輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹並返回。

法:首先需要了解前序遍歷和中序遍歷的特點,通過前序遍歷表先找到將要構建的子樹的根節點,然後在中序遍歷表中找相同的節點,那麼它的左邊就是左子樹,右邊就是右子樹,然後繼續按照這個規律劃分,遞歸建立就可以了。

代碼實現

5.題目:兩個棧實現隊列

    用兩個棧來實現一個隊列,完成隊列的Push和Pop操作。 隊列中的元素爲int類型。

解法:有兩個棧stack1,stack2,用stack1來完成隊列的push操作,用stack2來完成pop操作,當進行pop的時候,先判斷stack2裏是否還有元素,如果沒有,先將stack1裏的元素放進stack2中,然後再實現pop。

代碼實現

6.題目:旋轉數組的最小數字

    把一個數組最開始的若干個元素搬到數組的末尾,我們稱之爲數組的旋轉。 輸入一個非遞減排序的數組的一個旋轉,輸出旋轉數組的最小元素。 例如數組{3,4,5,1,2}爲{1,2,3,4,5}的一個旋轉,該數組的最小值爲1。 NOTE:給出的所有元素都大於0,若數組大小爲0,請返回0。

   解法:這個題要利用旋轉數組的特性。旋轉數組具有兩個或一個有序的序列,可以用二分的方法逐步逼近最小的值,假設中間元素取mid,二分的左值是lt,右值是rt,如果mid >= lt 說明還在第一個遞增序列裏,那讓二分的左值從mid開始,否則不處理。如果mid <= lt ,說明mid在第二個遞增序列裏,那麼讓二分的右值從mid 開始。一種特殊情況是:5        2 2 1 2 2,這種的需要在完成第一個分支的之後加上continue;(牛客網數據太水)。

代碼實現

7.題目:斐波那契數列

    大家都知道斐波那契數列,現在要求輸入一個整數n,請你輸出斐波那契數列的第n項。(n<=39)

    解法:F( i ) = F( i - 1 ) + F( i - 2 ),其中F( i ),F(i - 1) ,F( i - 2 )可以直接用變量來代替。

    代碼實現

8.題目:跳臺階

    一隻青蛙一次可以跳上1級臺階,也可以跳上2級。求該青蛙跳上一個n級的臺階總共有多少種跳法。

    解法:可以用dp的思想來做:dp( i ) = dp( i - 1) + dp( i - 2) ,也就是 i 級臺階的跳法數等於 i - 1級的跳法數和 i - 2級的跳法數的和。

    代碼實現

   本題目的變形:一隻青蛙一次可以跳上1級臺階,也可以跳上2級。但是由於該青蛙比較年幼,所以不能連續跳兩個臺階,求該青蛙跳上一個n級的臺階總共有多少種跳法。

   解法:直接上公式:dp[ i ] = dp[ i - 1] + dp[ i - 3] ,也就是從i - 1跳一步  +  從 i - 3 跳 1 步然後跳兩步。 

9.題目:變態跳臺階

    一隻青蛙一次可以跳上1級臺階,也可以跳上2級……它也可以跳上n級。求該青蛙跳上一個n級的臺階總共有多少種跳法。

    解法:公式: F[ i ] = F [ i - 1] + F[ i - 2] + F[ i - 3] .....F[1],同理 F[i - 1] = F[ i - 2] .......F[1]。兩式相減的F[i ] = 2F[i - 1]。進一步簡化

F[ i ] = 2^(i-1)(i >= 1)。

代碼實現

10.題目:矩形覆蓋

    我們可以用2*1的小矩形橫着或者豎着去覆蓋更大的矩形。請問用n個2*1的小矩形無重疊地覆蓋一個2*n的大矩形,總共有多少種方法?

   解法:公式 : dp[ i ] = dp [ i - 1] + dp[ i - 2],i - 1的加上 ,i - 2的,其中i - 2的放兩個豎型的小矩形和i - 1的重複了,所以加一個i - 2。

代碼實現

12.題目:數值的整數次方

    給定一個double類型的浮點數base和int類型的整數exponent。求base的exponent次方。

    解法:用C++完全可以用pow( )函數直接搞定。但是看網上許多人都是考慮了許多的情況。。。。。。。

    代碼實現

13.題目:調整數組順序使得奇數位於偶數前面

    輸入一個整數數組,實現一個函數來調整該數組中數字的順序,使得所有的奇數位於數組的前半部分,所有的偶數位於位於數組的後半部分,並保證奇數和奇數,偶數和偶數之間的相對位置不變。
    解法:一種複雜度高點的方法是,利用兩個指正,i 指向偶數,j 指向奇數,且 j 在 i 後面,因爲題目中提到移動後相對順序不變,所以如果 i 和 j 之間還有偶數,則讓 i 和 j 之間的數統一後移一位,然後將 j 處的值賦給 i 處,繼續這樣做。另一個種方法是犧牲空間換時間,只要另開闢一個數組就好了。

     代碼實現

14.鏈表中倒數第k個結點

    輸入一個鏈表,輸出該鏈表中倒數第k個結點。

    解法:這個題比較典型,經常見到。思路就是設置兩個指針,這裏假設是 p_first 和 p_second,然後 p_first 先遍歷,一直遍歷到第 k 個結點(如果有的話),然後讓 p_second指向一個節點,最後兩個指針一起向後遍歷,當 p_first 指向最後一個節點的時候,p_first 自然就指向倒數第 k 個結點了。

    注意:需要控制一下邊界,比如,當傳過來的頭指針爲空的時候,當 k 小於等於 0 的時候,還有鏈表不到 k 個結點的情況。這可以看出,當題目特別簡單的時候就需要注意一些細節問題,當然,題目難實現的時候也要注意(我這是說的啥) 。。。。

代碼實現

15.反轉鏈表(好題)

    輸入一個鏈表,反轉鏈表後,輸出鏈表的所有元素。

    解法:這題很好,剛開始我是加了一個函數,然後遞歸了一下,讓後一個的指針指向前一個,竟然可以不用遞歸,呵呵!說一下解法,有點像swap()交換變量那樣,一模擬就明白了,看代碼吧。

    代碼實現

30.題目:連續子數組的最大和

    HZ偶爾會拿些專業問題來忽悠那些非計算機專業的同學。今天測試組開完會後,他又發話了:在古老的一維模式識別中,常常需要計算連續子向量的最大和,當向量全爲正數的時候,問題很好解決。但是,如果向量中包含負數,是否應該包含某個負數,並期望旁邊的正數會彌補它呢?例如:{6,-3,-2,7,-15,1,2,2},連續子向量的最大和爲8(從第0個開始,到第3個爲止)。你會不會被他忽悠住?(子向量的長度至少是1)。

    解法:最大連續子串和。

代碼實現

35.題目:數組中的逆序對

    在數組中的兩個數字,如果前面一個數字大於後面的數字,則這兩個數字組成一個逆序對。輸入一個數組,求出這個數組中的逆序對的總數P。並將P對1000000007取模的結果輸出。 即輸出P%1000000007

    解法:使用改變後的歸併排序。

代碼實現

36.題目:兩個鏈表的第一個公共節點

    輸入兩個鏈表,找出它們的第一個公共結點。

    解法:比較簡單,可以畫一下這兩個列表如果有公共結點的時候的圖,會發現從他們的公共結點開始一直到最後一個結點,他們都是一樣的。這樣的話,我們只需要計算兩個鏈表的長度,然後讓較長的那個鏈表先遍歷他們長度差的大小,這樣兩個鏈表的長度就一樣了,就可以依次判斷兩個結點是否相等了。

代碼實現

37.題目:數字在排序數組中出現的次數

     統計一個數字在排序數組中出現的次數。

      解法:直接用lower_bound()計算一個位置,upper_bound()計算一個位置,然後相減就可以了,複雜度O(2logn);

代碼實現

40.題目:數組中只出現一次的數字

   一個整型數組裏除了兩個數字之外,其他的數字都出現了兩次。請寫程序找出這兩個只出現一次的數字。

   代碼實現

56.題目:刪除鏈表中重複的節點

    在一個排序的鏈表中,存在重複的結點,請刪除該鏈表中重複的結點,重複的結點不保留,返回鏈表頭指針。 例如,鏈表1->2->3->3->4->4->5 處理後爲 1->2->5。

代碼實現


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