最大回撤率 和 移動數組零元素到末尾

最大回撤率
將數組中零元素移動到末尾,要求算法時間複雜度爲O(n),空間複雜度爲O(1)

最大回撤率: 在選定週期內任一歷史時點往後推,產品淨值走到最低點時的收益率回撤幅度的最大值。最大回撤率用來描述買入產品後可能出現的最糟糕情況。D爲某一天的淨值,i 爲某一天,j 爲i 後的某一天,Di 是第i 天的產品淨值,Dj 是第j 天的產品淨值 最大回撤率:drawdown=max [(Di - Dj) / Di]

注意這道題不能簡單地找數組中最大最小值,然後計算落差,因爲有時間的先後順序存在,比如,2,9,4,3這四個數,9出現在2後面,只能計算:
(9-4)/9=0.55
(9-3)/9=0.66
(4-3)/4=0.25
最大回撤率應該是0.66,起始值爲9,結束值爲3.

解題思路可以來看一張圖:(圖片來源於他人博客
在這裏插入圖片描述
其中紅色曲線表示各個數據點,藍色點表示的是某段區間內的最大值,第5個點出我們可以看到最大落差。

numpy中有很好的工具實現這個過程:

def max_draw_down(arr):
	# i 爲結束位置
	i = np.argmax((np.maxinum.accumulate(arr) - arr)/np.maxinum.accumulate(arr))
	if i == 0:
		print("bullshit")
	# j 爲開始位置
	j = np.argmax(arr[:i])
	return (arr[j]-arr[i])/arr[j]

‘’’
numpy.argmax 找到最大元素的下標

numpy.ufunc.accumulate :官網的解釋是 accumulate the result of applying the operator to all elements,個人理解是累加將ufunc方法應用到每個元素上後的值,比如 numpy.add.accumulate([1, 2, 3])=[1, 3, 6],numpy.multiply.accumulate([ 4, 5, 6]) = [4, 20, 120]

numpy.maxinum :compare two arrays and returns a new array containing the element-wise maxima。 比較兩個數組並返回包含最大元素的新數組。比如:
np.maxinum([2, 3, 4], [5, 1, 3]) = [5, 3, 4]

所以: numpy.maxinum.accumulate就能計算出上圖中的那些藍點,對數組中每前後兩個元素對比,保留較大的那個,直到遇到一個更大的值。
‘’’

由於我對numpy不熟,筆試的時候就沒想到這麼精簡的代碼,我的想法是,對於當前某一個值arr_i,當其爲起始值時,取後序隊列中的最小值能達到該位置的最大回撤值。(唉,其實感覺自己也是一個很笨的人,很多題目都只能想到最簡單最原始的方法)

def find_min(arr):
	min_index = 0
	for i in range(len(arr)):
		if arr[i] < arr[min_index]:
			min_index = i
	return min_index

def max_down(arr):
	max_d = -1
	start = -1
	end = -1
	min_index = find_min(arr)
	for i in range(len(arr)):
		if i >= min_index:
			min_index = find_min(arr[i + 1: ])
		d = (arr[i] - arr[min_index]) / arr[i]
		if d > max_d:
			max_d = d
			start = i
			end = min_index
	if max_d == 0:
		print("bullshit")
	else:
		print(str(max_d) + "," + str(start) + "," + str(end))
將數組中的零元素移動到數組末尾,要求算法時間複雜度爲O(n),空間複雜度爲O(1)

當時我的代碼是:

def move_zeors(arr):
	for i in range(len(arr)):
		if arr[i]== 0:
			arr[i], arr[len(arr)-1-i] = arr[len(arr)-1-i], arr[i]
後面面試官提醒我可以改進,於是在數組末尾可以增加一個尾指針,記錄尾零的最小下標,當前指針到達尾指針處時不再走動。

還有一個最簡單的方法,當數組中零較多時,記錄數組長度,一次遍歷輸出非零數字,再補零即可。

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