簡體   English   中英

尋找 f(x) = a*min(b, x) 形式的函數最大值的算法?

[英]Algorithm for finding max value of functions of the form f(x) = a*min(b, x)?

我有一個元組(a, b)數組,其中a > 0b > 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)

所以問題是這些元組可以按ab排序。 但是它們之間可能有很多交叉點(如果我們將它們可視化為圖形)。 所以我想避免任何 O(n^2) 排序算法來檢查x的某些范圍,這是最好的 function。 我的意思是我不想將每個 function 與所有其他人進行比較,以找到從哪個點x' (交點)開始,我應該選擇一個。

假設ab和查詢的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 > ac*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<=x5<=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 個問題。 如果你能回答這兩個問題,那么你就可以回答整體問題:

  1. b<=x(a, b)對中,哪一個給出f(x,a,b) = a*b的最高值?
  2. 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM