有一段時間沒有寫博客了。今日閑逛的時候,看到一篇博客“4月7日某公司在華南地區舉辦了一年一度的"開發者"聚會——記某公司筆試”。里面有作者回憶的面試題。其中一題引起了筆者的注意,題目如下:
題目:已知一個數組a[N],構造一個數組b[N],構造規則:b[i]=a[0]*a[1]*a[2]...a[N]/a[i];
要求:
1、不可以使用除法;
2、時間復雜度為O(n),空間復雜度為S(0);
3、除遍歷使用的變量外,不可以使用其它變量;
看似簡單,想想也廢了一番腦筋。
最先想到的是就是原作者想到的方法,代碼如下(用的是VB2008):
Dim B(A.Length - 1) As Double
Dim I As Integer
B(0) = 1
For I = 0 To A.Length - 1
B(0) *= A(I)
Next
For I = A.Length - 1 To 0 Step -1
B(I) = B(0) / A(I)
Next
Return B
End Function
這個方法還是比較簡潔的,沒有多余的代碼。唯一不符合要求的就是用了除法
那還是老老實實的用最基本的方法,代碼如下:
Dim B(A.Length - 1) As Double
Dim I As Integer, J As Integer
For I = 0 To A.Length - 1
B(I) = 1
For J = 0 To A.Length - 1
If I <> J Then B(I) *= A(J)
Next
Next
Return B
End Function
雖然計算量上去了,但沒有用除法。不過算法的時間復雜度為O(N*N),不符合題目要求。而且這種方法比較死板,筆者不推薦。
想了很久,總是在使用除法和時間復雜度之間沒法平衡。
突然,一個念頭一閃而過。除法?轉一個彎如何?轉成減法如何?
利用公式S/A=10lgS-lgA
於是本題就變成
S=A(0)*A(1)*A(2)……*A(N)
B(I)=10lgS-lgA(I)
代碼如下:
Dim B(A.Length - 1) As Double
Dim I As Integer
B(0) = 1
For I = 0 To A.Length - 1
B(0) *= A(I)
Next
For I = A.Length - 1 To 0 Step -1
B(I) = 10 ^ (Math.Log10(B(0)) - Math.Log10(A(I)))
Next
Return B
End Function
符合題目要求了么?符合了,沒用除法,時間復雜度也是O(N)。只是效率稍微低了點。
但是效率真的低么?不見得,VS對Log10函數做了優化,雖然低了點,但是可以忽略不計。
利用高中階段的對數公式,另類的解決了該問題。如果誰還有更好的算法,望不吝賜教。大家互相學習,共同提高。
