1. 程式人生 > >劍指offer題目系列一

劍指offer題目系列一

過程 一個數 1-1 二維數組 等於 style 所有 RR htm

本篇介紹《劍指offer》第二版中的四個題目:找出數組中重復的數字、二維數組中的查找、替換字符串中的空格、計算斐波那契數列第n項。

這些題目並非嚴格按照書中的順序展示的,而是按自己學習的順序,每個題目包含了分析和代碼,代碼都是用Java語言編寫的。

1、找出數組中重復的數字

題目:
在一個長度為n的數組裏,所有數字都在0~n-1的範圍內。數組中某些數字是重復的,但不知道有幾個數字重復,也不知道每個數字重復了幾次,請找出數組中任意一個重復的數字。例如,如果輸入長度為7的數組{2,3,1,0,2,5,3},那麽對應的輸出是重復的數字2或者3。
解答:
這裏提供兩種方式。
第一種方式:本題所有數字都在0~n-1的範圍內,如果數組中沒有重復的數字,那麽數組排序之後數字i與其下標i的值是一一對應的,即0-0、1-1、2-2……由於有重復數字,則排序後有些位置可能有多個數字,有些位置可能沒有數字。
這種方式的思路就是將數字i放到其下標i處,如果存在兩個下標對應的數字相等,則說明有重復,該數字就是一個重復的數字。
代碼:

技術分享圖片

代碼中盡管有兩重循環,但每個數字最多只要交換兩次就能找到它自己的位置,因此總的時間復雜度為O(n),同時空間復雜度為O(1),因此推薦此方法。
第二種方式:用HashMap或ArrayList,都是先從第一個元素開始遍歷數組,如果HashMap或ArrayList中不存在該元素,則將其放入,如果存在,則說明有重復。這種方式需要額外的空間,時間復雜度和空間復雜度都為O(n)。
代碼:

技術分享圖片

這裏僅僅以HashMap為例,ArrayList與其類似,不再贅述。

2、二維數組中的查找

題目:
在一個二維數組中,每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函數,輸入這樣的一個二維數組和一個整數,判斷數組中是否含有該整數。
解答:
這裏提供4種類似的方式:可以先從二維數組右上角(第一行最後一列)的數字開始比較,如果它比要查找的數字小,則第一行所有數字都比它小,說明該數字不在第一行。然後比較第二行最後一列數字,如果比要查找的數字大,則說明在第二行,然後將第二行的數組按倒序的順序逐個與其比較,直到找到為止。這種方式是從第一行往下逐行排除,找到目標數字所在的行以後,按倒序逐列排除。另外三種方式分別是從最後一行往上逐行排除,找到目標數字所在的行以後,按正序逐列排除;從最後一列往左逐列排除,找到目標數字所在的列以後,按正序逐行排除;從第一列往右逐列排除,找到目標數字所在的列以後,按倒序逐行排除。
下面代碼僅說明其中的兩種按行排除的方式。
代碼:

技術分享圖片

技術分享圖片

3、替換字符串中的空格

題目:
請實現一個函數,把字符串中的每個空格替換成“%20”。例如,輸入“We are happy.”,則輸出“We%20are%20happy.”。
解答:
這裏提供2種方式。
第一種方式:先統計出原字符串中空格個數,並計算出替換之後字符串的長度,然後新建一個數組,使其長度等於替換之後字符串的長度,用於存放替換之後字符串。
如果從前往後遍歷字符串,碰到空格就替換,那麽後面的字符可能會多次移動,總的時間復雜度為O(n2),效率不高。因此這裏從後往前遍歷原字符串,如果是非空格字符,就直接復制到新數組中(註意新數組也是從後往前放入字符);如果是空格,則按0、2、%的順序放入新數組……直到遍歷完字符串為止,這樣就能保證每個元素只會移動一次,時間復雜度為O(n)。
代碼:

技術分享圖片

第二種方式:因為Java語言中String類型字符串是無法改變的,而StringBuilder和StringBuffer類型字符串是可以改變的,因此可以用這兩個類型,通過append()方法拼接字符串。如果對線程安全有要求,則可以用StringBuffer,沒要求可以用StringBuilder。以下以StringBuilder為例,StringBuffer與其類似。

技術分享圖片

4、計算斐波那契數列第n項

題目:
求斐波那契數列的第n項。寫一個函數,輸入n,求斐波那契數列的第n項。
斐波那契數列定義如下:第1項F(1)=1,第2項F(2)=1,從第3項開始,每一項都等於前兩項之和。前幾項數字為:1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377……
解答:
這裏提供兩種方式:非遞歸方式和遞歸方式。
第一種方式,非遞歸方式(優先選擇)。定義三個變量,分別存放前兩項和第三項(當前項)的值,逐個計算斐波那契數列的每一項,直到第n項停止並返回。只有一個循環,時間復雜度為O(n)。
代碼:

技術分享圖片

第二種方式,遞歸方式。遞歸方式的代碼很簡潔,但仔細分析就會發現,遞歸方式計算的過程中會產生大量重復計算。比如想求f(10),得先計算出f(9)和f(8);同樣想求出f(9),得先計算出f(8)和f(7);想求出f(8),得先計算出f(7)和f(6)……可以看到f(8)、f(7)等項都求了兩次值。當n很大時,重復計算量會非常大,效率會很低,因此這種方式當n很小時還可以,很大時就不太適用了。所以優先推薦第一種方式。
代碼:

技術分享圖片

轉載請註明出處 http://www.cnblogs.com/Y-oung/p/8858960.html

工作、學習、交流或有任何疑問,請聯系郵箱:[email protected] 微信:yy1340128046

劍指offer題目系列一