[英]Algorithm for finding max value of functions of the form f(x) = a*min(b, x)?
我有一個元組(a, b)
數組,其中a > 0
和b > 0
。
每個元組代表一個 function f
使得f(x, a, b) = a * min(b, x)
。
對於給定的x
是否有已知的算法來查找哪個元組返回最大值?
我不想評估每個 function 來檢查最大值,因為我會針對不同的x
查詢這個數組任意次數。
例子:
array = [ (1, 10), (2, 3) ]
x < 6 -> choose (2, 3)
x = 6 (intersection point) -> either (1, 10) or (2, 3) doesn't matter
x > 6 -> choose (1, 10)
所以問題是這些元組可以按a
或b
排序。 但是它們之間可能有很多交叉點(如果我們將它們可視化為圖形)。 所以我想避免任何 O(n^2) 排序算法來檢查x
的某些范圍,這是最好的 function。 我的意思是我不想將每個 function 與所有其他人進行比較,以找到從哪個點x'
(交點)開始,我應該選擇一個。
假設a
、 b
和查詢的x
總是非負數,每個查詢可以在O(n*log(n))
O(log(n))
時間內完成:
預處理步驟消除了嚴格受他人支配的此類功能。 例如,對於每個 x, (5, 10)
都大於(1, 1)
。 (因此,如果數組中有(5, 10)
,那么我們可以刪除(1, 1)
因為它永遠不會是任何 x 的最大值。)
這是一般條件:當且僅當c > a
和(c*d > a*b)
時,對於每個 x,A function (a, b)
大於(c, d)
) 。 (這很容易證明。)
現在,我們要做的是刪除存在 a (c, d)
的函數(a, b)
使得c > a
和(c*d > a*b)
。 這可以在 O(n*log(n)) 時間內完成:
1 - 按字典順序對元組進行排序。 我的意思是按字典順序首先比較它們的第一個坐標,如果它們相等,然后比較第二個坐標。 例如,排序后的數組可能如下所示:
(1, 5)
(1, 17)
(2, 9)
(4, 3)
(4, 4)
2 - 以相反的順序遍歷已排序的數組,並跟蹤到目前為止您遇到的a*b
的最大值。 我們稱這個值M
。 現在,假設我們在循環中處理的元素是(a, b)
。 如果a*b < M
,我們刪除這個元素。 因為對於我們之前處理的一些(c, d)
, c > a
和c*d > a*b
,因此(a, b)
是無用的。 在這一步之后,示例數組將變為:
(2, 9)
(4, 4)
(4, 3)
被刪除,因為它被(4, 4)
支配。 (1, 17)
和(1, 5)
被刪除,因為它們由(2, 9)
支配。
一旦我們去掉了所有對於任何 x 都不是最大值的函數,剩下的函數的圖形將如下所示。
如圖所示,每個 function 是從與前一個相交的點到與后一個相交的點的最大值。 對於上面的示例, (4, 4)
和(2, 9)
在x = 8
處相交。 所以(4, 4)
是最大值,直到x = 8
,在那之后, (2, 9)
是最大值。 我們想計算數組中連續函數相交的點,這樣對於給定的 x,我們可以對這些點進行二分搜索,以找到 function 返回的最大值。
效率的關鍵是避免無用的工作。 如果您想象一棵決策樹,那么修剪分支是一個經常用於此的術語。
對於您的情況,決策基於在兩個函數(或參數元組)之間進行選擇。 為了 select 這兩個函數中的任何一個,您只需確定它們為您提供相同值的值x
。 其中一個對於較小的值表現更好,一個對於較大的值。 另外,不要忘記這部分,可能一個 function總是比另一個表現更好。 在這種情況下,可以完全刪除表現較差的那個(另見上文,避免無用的工作。)。
使用這種方法,您可以將 map 從這個切換點切換到左側的 function。 找到任意值的最佳 function 只需要找到下一個更高的切換點。
順便說一句:確保你有單元測試。 這些東西很繁瑣,尤其是浮點值和舍入錯誤,所以你要確保你可以運行越來越多的測試套件,以確保一個小錯誤修復不會破壞其他地方的東西。
我認為您應該先根據“b”對數組進行排序,然后再根據“a”對數組進行排序。 現在對於每個 x 只需使用二進制搜索並找到 position 從中 min(b,x) 將根據值僅給出 b 或 x。 因此,從那時起,如果 x 很小,那么 b 的所有即將到來的值然后將元組作為 t1 並且您可以使用該 function 和 b 的值來計算值,該值將小於 x 您必須遍歷。 我不確定,但這就是我能想到的。
預處理數據后,可以在O(log(n))
時間內計算出這個最大值,其中n
是元組的數量(a, b)
。
首先,讓我們看一個稍微簡單的問題:您有一個對(c, b)
的列表,並且您想要找到具有最大值的一對c
,條件是b<=x
,並且您想要為不同的x
值多次執行此操作。 例如,以下列表:
c b
------
11 16
8 12
2 6
7 9
6 13
4 5
有了這個列表,如果你用x=10
詢問, c
的可用值為 2、7 和 4,最大值為 7。
讓我們按b
對列表進行排序:
c b
------
4 5
2 6
7 9
8 12
6 13
11 16
當然,這個列表中的某些值永遠無法給出答案。 例如,我們永遠不能在答案中使用b=2
, c=6
行,因為如果6<=x
則5<=x
,所以我們可以使用c=4
行來獲得更好的答案。 所以我們不妨去掉列表中類似的對,即所有c
的值不是迄今為止最高的對。 因此,我們將列表縮減為:
c b
------
4 5
7 9
8 12
11 16
鑒於此列表,在b
上有一個索引,很容易找到c
的最大值。 您所要做的就是在列表中找到b
的最大值<=x
,然后返回c
的對應值。
顯然,如果您更改問題以便只需要b>=x
(而不是b<=x
)的值,您可以做完全相同的事情。
正確的。 那么這對您提出的問題有何幫助?
對於給定的x
值,您可以將問題分成 2 個問題。 如果你能回答這兩個問題,那么你就可以回答整體問題:
b<=x
的(a, b)
對中,哪一個給出f(x,a,b) = a*b
的最高值?b>=x
的對(a, b)
中,哪一個給出f(x,a,b) = a*x
的最高值? 對於 (1),簡單地讓每對c=a*b
,然后通過上面概述的整個索引復雜性讓 go。
對於(2),讓c=a
並執行上面的索引操作,但翻轉以執行b>=x
而不是b<=x
; 當你得到a
的答案時,不要忘記將它乘以x
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.