最大化最小值和最小化最大值

2021-09-28 19:53:19 字數 3728 閱讀 1653

最小化最大值是為了壓制優化目標中表現最突出的成分,最大化最小值為了提公升優化目標中表現最差的成分

關於這兩者的理解,我覺得這篇博文講得非常好,淺顯易懂又聯絡實際。

理解問題後,就要思考如何解決問題。

記住,這兩類問題一般都是用問題轉換加二分查詢的方法解決。

我會用**+詳細注釋的形式記錄這兩類問題的解法,題目描述易於理解,耐心看完再看題解才會有收穫。

最大化最小值問題:leetcode

你有一大塊巧克力,它由一些甜度不完全相同的小塊組成。我們用陣列 sweetness 來表示每一小塊的甜度。

你打算和 k 名朋友一起分享這塊巧克力,所以你需要將切割 k 次才能得到 k+1 塊,每一塊都由一些 連續 的小塊組成。

為了表現出你的慷慨,你將會吃掉 總甜度最小 的一塊,並將其餘幾塊分給你的朋友們。

請找出乙個最佳的切割策略,使得你所分得的巧克力總甜度最大,並返回這個 最大總甜度。

示例 1:

輸入:sweetness = [1,2,3,4,5,6,7,8,9], k = 5

輸出:6

解釋:你可以把巧克力分成 [1,2,3], [4,5], [6], [7], [8], [9]。

示例 2:

輸入:sweetness = [5,6,7,8,9,1,2,3,4], k = 8

輸出:1

解釋:只有一種辦法可以把巧克力分成 9 塊。

示例 3:

輸入:sweetness = [1,2,2,1,2,2,1,2,2], k = 2

輸出:5

解釋:你可以把巧克力分成 [1,2,2], [1,2,2], [1,2,2]。

0 <= k < sweetness.length <= 10^4

1 <= sweetness[i] <= 10^5

題目描述中我用下劃線標註出來的語句點明了這是一道最大化最小值的問題。拋開題目情景,這道題其實可以描述為:

給定乙個陣列,將陣列分割成k+1個連續的子陣列,求一種分割方法可以使得分割後的所有子陣列的和的最小值,比其他分割方法得到的子陣列的和最小值都大。要求輸出這個最大的最小值。

我們知道乙個陣列的子陣列可以是它本身,也可以是乙個只包含陣列中任一元素的陣列。所以我們可以求出陣列的最小值(設為a)以及陣列的和(設為b),那麼我們要找的最大的最小值必定屬於[a,b)。

因此,問題可以轉為在[a,b)中找到乙個最大的數(最大化)使得存在一種分割方法可以讓所有子陣列的和大於或等於這個數(最小值)

由於[a,b)是有序的,所以在有序序列中找數,可以用二分查詢

那麼如何找到上述的分割方法?

首先確定一點,這種分割方法要讓所有子陣列的和大於或等於某個數(設為n),那麼我們就要盡量讓其中的子陣列的和與m的差值小一些。假設有乙個子陣列的和遠遠超過n,那就說明其他子陣列可以分到的元素很少,難以保證其他子陣列的和也能超過m。這就像有時候我們在分配物資一樣(前提是所有物資都必須分配完),在物資充足的情況下,我們說要讓每個人都至少有n件物資,結果一開始分配的時候就有一老哥上來拿走了遠超過n件的物資然後就溜了,結果剩下的物資就難以保證每個人都至少有n件了,剩下的人肯定不願意。所以一開始分配給那位老哥的時候,我們就不能讓他自己拿,應該一件一件地給他,給到n件了就讓他走人,這樣才能保證最後大家都有至少有n件。而如果一開始物資就不足以讓每個人都至少有n件,那按照這個方法分到最後肯定有人沒有拿到n件物資。這樣的話,我們通過記錄多少人拿了n件物資,就能夠區分我們手頭的物資到底能不能讓每個人都至少有n件。

上面的描述轉換為我們討論的陣列和子陣列,就是對於第乙個子陣列,我們依次分配給它原陣列的元素直到它的和超過了n,那我們就不分配了,開始給第二個子陣列分配了。最終看有多少個子陣列的和大於或等於n。假設我們要求應該有t個這樣的子陣列,而實際上根據我們的分配得到的滿足要求的子陣列的個數是m。若m>t,則說明以n為最小值完全可以滿足我們的要求,n甚至可以再大些;若mt中,在下面的**後會說明(結合**說比較清楚)。

鋪墊了這麼多,可以寫**了:

class solution 

while(left& sweetness,int cuts,int target)

if(cnt>cuts)

return true;

}return false;

}};

上面**中的cancut函式為什麼不考慮cnt=cuts+1的情況(即達到要求的子陣列個數與題目要求的個數相同)?這種情況下的target就是我們要找的最大化最小值嗎?

不是的,因為有可能陣列的最後乙個陣列很大使得最後乙個子陣列的和超過2*target,那麼實際上target還可以再設定為更大點。

最小化最大值問題:leetcode

給定乙個非負整數陣列和乙個整數 m,你需要將這個陣列分成 m 個非空的連續子陣列。設計乙個演算法使得這 m 個子陣列各自和的最大值最小。

注意:陣列長度 n 滿足以下條件:

1 ≤ n ≤ 1000

1 ≤ m ≤ min(50, n)

示例: 

輸入:nums = [7,2,5,10,8]

m = 2

輸出:18

解釋:一共有四種方法將nums分割為2個子陣列。

其中最好的方式是將其分為[7,2,5] 和 [10,8],

因為此時這兩個子陣列各自的和的最大值為18,在所有情況中最小。

這題題目描述已經相當明確了,沒有最大化最小值那題的情景設計。

我在一開始說過,這兩類問題的基本思路是一樣的,核心是二分查詢。看了上面我的那一大段最大化最小值的解釋後應該很快能模擬出這題的思路。

首先明確,要求的是「最大值」,其次才是最小化的最大值。那麼假設原陣列中最大的元素值為a,陣列的和為b,那我們要求的這個最大值一定屬於[a,b),所以我們在[a,b)中二分查詢。

要使最大值最小,那麼在分配子陣列時我們應該盡量讓每個子陣列足夠的大。

還是拿分配物資來舉例。現在我們的目標是讓分配給某個人的物資不能超過k件(前提是所有物資都必須分配完)。那麼如果一開始我們分配給前面的人的時候分配得很少,那麼後面的人就越有可能分配到超過k件物資。因此我們要從一開始就盡可能地多分配物資,但不超過k件。

回到陣列中,即我們要讓第乙個子陣列盡可能的接近k但不超過k(可以等於,這時這個陣列可能就是那個最小化最大值的子陣列和了),當再分配乙個元素給第乙個子陣列時,其和超過k,那這個元素我們不分配給它,我們分配給第二個子陣列,以此類推。

若最終分割到的子陣列的個數為m,而我們要求的子陣列的個數為t。當m>t時,說明有太多的子陣列的和接近k,我們可以讓k再大一點,以減少m。當m下面的**採用long long做運算是因為不確定資料的取值範圍,怕發生整數溢位。

class solution 

if(cnt>cuts) //這就是m>=t的情況,至於》=為什麼可以歸於一類,道理同最大化最小值最後我解釋的一樣

return false;

}return true;

}};

如果你要問怎麼上面**的二分就不用left+right+1,那你得好好溫習一下二分查詢了,二分查詢雖然簡單,但有時候自己實現起來還說不定bug重重,不斷tle。

希望從此我能很快解決這兩類問題!從理解到熟記於心!

如何理解最大化最小值問題和最小化最大值問題

min max和max min在優化問題中比較常見,一句話說 min max是為了壓制優化目標中表現最突出的成分,max min為了提公升優化目標中表現最差的成分。為了把這兩個問題作乙個比較通俗的解釋,方便筆者和各位讀者對此問題有更直觀的理解。先理解這個問題,借用之前看到的乙個例子 考慮規劃城市中急...

二分搜尋 (最小值最大化和最大值最小化)

有一類常見問題叫做最小值最大化或者最大值最小化。這類問題一般是用二分搜尋來解決。首先二分搜尋解決的問題必須具備單調性這個性質,這是使用二分搜尋的必要條件,我們分析兩個問題。1.最小值最大化 我們假設x為最大的最小值,那麼x 1是滿足條件的,但他並不滿足最大,x 1是不滿足條件的,假設我們左邊界是l,...

二分查詢求最大值最小化(最小值最大化)問題

題目描述 這項比賽將在一條筆直的河道中進行,河道中分布著一些巨大岩石。組委會已經選擇好了兩塊岩石作為比賽起點和終點。在起點和終點之間,有 nn 塊岩石 不含起點和終點的岩石 在比賽過程中,選手們將從起點出發,每一步跳向相鄰的岩石,直至到達終點。為了提高比賽難度,組委會計畫移走一些岩石,使得選手們在比...