通常,您不希望使用循環來實現F#中的複雜迭代/遞歸函數。這就是尾遞歸函數的優點。
爲了得到低於O(n2)的計算複雜度,怎麼樣:考慮一組候選加數,它是最初的一組完整數字。現在看看這個集合中最大和最小數字的總和。如果該總和大於目標號碼,則最大號碼不會與任何事物的目標號碼相加。反過來也是如此。
繼續從候選組中刪除最小或最大的數字,直到該組爲空或已找到匹配。
的代碼看起來是這樣的:
let rec f M x =
if Set.isEmpty M then false else
let biggest, smallest = Set.maxElement M, Set.minElement M
let sum = biggest + smallest
if sum > x then f (Set.remove biggest M) x
elif sum < x then f (Set.remove smallest M) x
elif sum = x then true
else failwith "Encountered failure to compare numbers/NaN"
當我看的數學定義,它似乎並不爲目標數是集合的要求。但是,如果這個問題,只是事先檢查:
let fChecked M x =
if Set.contains x M then f M x
else invalidArg "x" "Target number is not contained in set."
湯姆使這個通用在可比的類型,功能可以被標記inline
。
設置的操作是O(log n),我們遍歷整個事情,乘以O(n),使得總複雜度爲O(n log n)(其中n是集合中元素的數量)。
有效極速版
如果它是關於實際速度,而不是「只是」計算複雜,數組可能更快,比一成不變套。下面是一個使用數組索引版本:
/// Version where M is types as an unsorted array we're allowed to sort
let f M x =
Array.sortInPlace M
let rec iter iLow iHigh =
if iLow > iHigh then false else
let sum = M.[iLow] + M.[iHigh]
if sum > x then iter iLow (iHigh - 1)
elif sum < x then iter (iLow + 1) iHigh
elif sum = x then true
else failwith "Encountered failure to compare numbers/NaN"
iter 0 (M.Length - 1)
需要注意的是,我們可以在數組,如果同組中重複使用預先排序,使這項工作的複雜每次調用同一組下降到爲O(n)。
這是偶然的作業嗎?當有人問大O的限制算法時,我只需要問。 O(n2)對於這個問題是顯而易見的。 –
@GuyCoder:嗯,這是一個任務,可以在後面的考試中提出,我正在嘗試寫在F#中;)謝謝你的第二個評論,主席先生 - 我意識到我忘記了一個'不' – Unknown6656
在這種情況下,使用Seq.find而不是循環 –